LINQ Check for Nulls with OR - performance

I have 2 values in table User: Address1, Address2. Both could be null. As part of a filter method, I am attempting something like the below:
var tempUsers = users.Where(q => q.Address1.ToLower().Contains(address.ToLower()) || q.Address2.ToLower().Contains(address.ToLower()));
This is returning a Null Reference Exception, and rightly so.
Linq queries need to be handled against null values
I would be attempting
null.ToLower() and null.Contains() within the query
What is the best way to go around it? If it was a simple 1 field Query, for e.g. just Address1, I would have simply filtered out all items with empty Address1, and continued normally in the second query. In this case, both fields are important to the filtering, as in, the input: address could be either in Address1 or Address2 of the User table.
I know this might not be possible in a 1 liner, but what is the best approach to take in terms of time and performance?

How about this:
var address = (GetAddressFromOuterWorld() ?? String.Empty).ToLower();
var tempUsers = users.Where(user => (user.Address1 ?? String.Empty).ToLower().Contains(address)
|| (user.Address2 ?? String.Empty).ToLower().Contains(address));
This definitely works with LINQ to Object, but probably fails with LINQ to SQL, but in that case you normally write user.Address1 == address || user.Addrss2 == address and your database uses a case-insensitive collate setting.

You can easily add null checks like this.
var tempUsers = users.Where(q =>
(!string.IsNullOrEmpty(q.Address1) && q.Address1.ToLower().Contains(address.ToLower())) ||
(!string.IsNullOrEmpty(q.Address2) && q.Address2.ToLower().Contains(address.ToLower())));

Related

Is it possible to detect if the selected item is the first in LINQ-to-SQL?

I wonder how I can build a query expression which understands the given item being selected is the first or not. Say I'm selecting 10 items from DB:
var query = db.Table.Take(10).Select(t => IsFirst ? t.Value1 : t.Value2);
There is an indexed variant of Select but that is not supported in LINQ-to-SQL. If it was supported my problems would be solved. Is there any other trick?
I could have used ROW_NUMBER() on T-SQL for instance, which LINQ-to-SQL uses but does not give access to.
I know I can Concat two queries and use the first expression in the first and so forth but I don't want to manipulate the rest of the query, just the select statement itself because the query is built at multiple places and this is where I want to behave differently on first row. I'll consider other options if that is not possible.
You can use the indexed overload, but you need to use the LINQ to Objects version:
var query =
db.Table.Take(10).AsEnumreable()
.Select((t, index) => index == 0 ? t.Value1 : t.Value2);
If Table have a primary key. You could do this:
var result= (
from t in db.Table.Take(10)
let first=db.Table.Take(10).Select (ta =>ta.PrimayKey).First()
select new
{
Value=(t.PrimaryKey=first?t.Value1 : t.Value2)
}
);

LINQ 2 Entities-query is not working, but why?

everyone! ))
Here is code.
var existingEntities = (from record in globalOne.serviceContext.records_out
where record.timestamp.Date == DateTime.Now.Date
select record ).ToList();
It doesn't work.
Another code:
var existingEntities = (from record in globalOne.serviceContext.records_out
where record.timestamp.Day == DateTime.Now.Day
select record ).ToList();
It does work.
So, problem id in next string:
where record.timestamp.**Date** == DateTime.Now.Date
also won't do
where record.timestamp.Date.Equals(DateTime.Now.Date)
But why? I have no clue. "Timestamp" field is dateTime field in MS SQL SERVER.
And - there is NO records in table.
And I almost forgot - what does it mean - "doesn't work".
App just will not reach the breakpoint after that query(first), without any error, without anything.
Thanks.
You can call record.timestamp.Date because EF can't convert it to required expression tree (then convert it to sql command). In fact EF supports limited number of functions and properties, But for DateTime, EF has some good Canonical functions. You can use them in your case, e.g you can use Day(),Month(),Year() functions to solve your problem (see the link).

using linq query with stringBuilder

I want to create dynamic where clause in a LINQ query. I have one stringbuilder sb having append values Country=null || City=null || State=null and one datatable that has column named Name, Lastname, Country, City, State. I want to compare sb values with datatable columns and get null / empty rows.
So I want a LINQ query like this:
var query = from p in datatable.AsEnumerable()
where sb.tostring() // ------------error
select p
but it returns an error. How can I solve this problem?
You can use Dynamic Linq
var query = datatable.Where("Country==null || City==null || State==null");
You'll need to download and include the C# file in the link and add:
using System.Linq.Dynamic;
You can't do that in LINQ. Dynamic LINQ might help you, but that's probably no the best solution for you.
Why are you creating the query as a string? You can just build the query itself dynamically. Have a look at PredicateBuilder.

Is this linq query efficient?

Is this linq query efficient?
var qry = ((from member in this.ObjectContext.TreeMembers.Where(m => m.UserId == userId && m.Birthdate == null)
select member.TreeMemberId).Except(from item in this.ObjectContext.FamilyEvents select item.TreeMemberId));
var mainQry = from mainMember in this.ObjectContext.TreeMembers
where qry.Contains(mainMember.TreeMemberId)
select mainMember;
Will this be translated into multiple sql calls or just one? Can it be optimised? Basically I have 2 tables, I want to select those records from table1 where datetime is null and that record should not exist in table2.
The easiest way to find out if the query will make multiple calls is to set the .Log property of the data context. I typically set it to write to a DebugOutputWriter. A good example for this kind of class can be found here.
For a general way of thinking about it however, if you use a property of your class that does not directly map to a database field in a where clause or a join clause, it will typically make multiple calls. From what you have provided, it looks like this is not the case for your scenario, but I can't absolutely certain and suggest using the method listed above.

LINQ syntax where string value is not null or empty

I'm trying to do a query like so...
query.Where(x => !string.IsNullOrEmpty(x.PropertyName));
but it fails...
so for now I have implemented the following, which works...
query.Where(x => (x.PropertyName ?? string.Empty) != string.Empty);
is there a better (more native?) way that LINQ handles this?
EDIT
apologize! didn't include the provider... This is using LINQ to SQL
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=367077
Problem Statement
It's possible to write LINQ to SQL that gets all rows that have either null or an empty string in a given field, but it's not possible to use string.IsNullOrEmpty to do it, even though many other string methods map to LINQ to SQL.
Proposed Solution
Allow string.IsNullOrEmpty in a LINQ to SQL where clause so that these two queries have the same result:
var fieldNullOrEmpty =
from item in db.SomeTable
where item.SomeField == null || item.SomeField.Equals(string.Empty)
select item;
var fieldNullOrEmpty2 =
from item in db.SomeTable
where string.IsNullOrEmpty(item.SomeField)
select item;
Other Reading:
1. DevArt
2. Dervalp.com
3. StackOverflow Post
This won't fail on Linq2Objects, but it will fail for Linq2SQL, so I am assuming that you are talking about the SQL provider or something similar.
The reason has to do with the way that the SQL provider handles your lambda expression. It doesn't take it as a function Func<P,T>, but an expression Expression<Func<P,T>>. It takes that expression tree and translates it so an actual SQL statement, which it sends off to the server.
The translator knows how to handle basic operators, but it doesn't know how to handle methods on objects. It doesn't know that IsNullOrEmpty(x) translates to return x == null || x == string.empty. That has to be done explicitly for the translation to SQL to take place.
This will work fine with Linq to Objects. However, some LINQ providers have difficulty running CLR methods as part of the query. This is expecially true of some database providers.
The problem is that the DB providers try to move and compile the LINQ query as a database query, to prevent pulling all of the objects across the wire. This is a good thing, but does occasionally restrict the flexibility in your predicates.
Unfortunately, without checking the provider documentation, it's difficult to always know exactly what will or will not be supported directly in the provider. It looks like your provider allows comparisons, but not the string check. I'd guess that, in your case, this is probably about as good of an approach as you can get. (It's really not that different from the IsNullOrEmpty check, other than creating the "string.Empty" instance for comparison, but that's minor.)
... 12 years ago :) But still, some one may found it helpful:
Often it is good to check white spaces too
query.Where(x => !string.IsNullOrWhiteSpace(x.PropertyName));
it will converted to sql as:
WHERE [x].[PropertyName] IS NOT NULL AND ((LTRIM(RTRIM([x].[PropertyName])) <> N'') OR [x].[PropertyName] IS NULL)
or other way:
query.Where(x => string.Compare(x.PropertyName," ") > 0);
will be converted to sql as:
WHERE [x].[PropertyName] > N' '
If you want to go change the type of the collection from nullable type IEnumerable<T?> to non-null type IEnumerable<T> you can use .OfType<T>().
.OfType<T>() will remove null values and return a list of the type T.
Example: If you have a list of nullable strings: List<string?> you can change the type of the list to string by using OfType<string() as in the below example:
List<string?> nullableStrings = new List<string?> { "test1", null, "test2" };
List<string> strings = nullableStrings.OfType<string>().ToList();
// strings now only contains { "test1", "test2" }
This will result in a list of strings only containing test1 and test2.

Resources