Linq query skip querying null coditions - linq

I am very new to linq. I have my clients table. I want to select clients depending on the two conditions
Client type
Client city
So I can write the query like
from c in clients
where c.Type == cType
&& c.City == cCity
Can I use this same query to get the result only providing client type(ignoring the City condition. somithing like *).
What I want to do is if cCity or cType is null ignore the condition.
Is this possible to do?

Isn't that what you're looking for?
from c in clients
where (c.Type == null || c.Type == cType)
&& (c.City == null || c.City == cCity)

You can compose a LINQ statement before actually executing it:
if (cType != null)
clients = clients.Where(c => c.Type == cType);
if (cCity != null)
clients = clients.Where(c => c.City== cCity);
// At this point the query is never executed yet.
Example of how the query can be executed for the first time :
var results = clients.ToList();

from c in clients
where (cType == null ? 1 == 1 : c.Type == cType)
&& (cCity == null ? 1 == 1 : c.City == cCity)

Related

How to pass an external parameter to LINQ where clause in CRM

I have a LINQ query which works fine as for stand alone lists but fails for CRM
var lst = new List<bool?>();
lst.Add(null);
lst.Add(true);
lst.Add(false);
bool IsWet = false;
var newlst = from exch_HideVoiceSignature in lst where
(((exch_HideVoiceSignature!=null && exch_HideVoiceSignature==false
|| exch_HideVoiceSignature== null) )&& !IsWet) select exch_HideVoiceSignature;
newlst.Dump();
var question = from q in exch_questionSet where ((q.exch_HideVoiceSignature != null
&& q.exch_HideVoiceSignature.Value == 0 )|| q.exch_HideVoiceSignature == null )
&& !IsWet select q.exch_HideVoiceSignature;
question.FirstOrDefault().Dump();
As you can see I can pass the variable IsWet to LINQ query for a standard list fine and get values for first list. But when I execute the same for second list, I get the following error
Invalid 'where' condition. An entity member is invoking an invalid property or method
The CRM LINQ provider won't support the evaluation you attempting. It only supports evaluation of where criteria is evaluating an entity field.
That's not a problem. Since you want the LINQ query to only use the where clause if IsWet is false (correct me if I'm wrong on that.) So we simply do the evaluation to determine if the where clause should be added or not. Then execute your query.
var question = from q in exch_questionSet
select q.exch_HideVoiceSignature;
if (!IsWet)
{
question.Where(x => ((x.exch_HideVoiceSignature != null
&& x.exch_HideVoiceSignature.Value == 0) || x.exch_HideVoiceSignature == null));
}
question.FirstOrDefault().Dump();
I am constantly confronted with that problem.
Try to "detach" (for example call .ToArray()) your query (while it is "clear") from CRM and then filter query using external parameter. This should help.
var question =
(from q in exch_questionSet
where (
(q.exch_HideVoiceSignature != null && q.exch_HideVoiceSignature.Value == 0 ) ||
q.exch_HideVoiceSignature == null )
select q.exch_HideVoiceSignature
).ToArray().Where(q => !IsWet);
question.FirstOrDefault().Dump();
UPDATE
If you are using IsWet flag to control blocks of conditions (enable and disable them from the one point in the code) then probably you may be interested in class named PredicateBuilder which allows you to dynamically construct predicates.
Just because I had an existing query with lot of other joins etc. and I wanted to pass this additional parameter to it I ended up using a var statement which dumps the rows to a list and applies the where clause in the same statement
bool IsWet =true ;
var question = ...existing query ...
select new {
...existing output ...,
Wet =q.exch_HideVoiceSignature != null &&
q.exch_HideVoiceSignature.Value == 119080001,
Voice = q.exch_HideVoiceSignature == null ||
(q.exch_HideVoiceSignature != null &&
q.exch_HideVoiceSignature.Value == 119080000) ,
}
;
var qq = IsWet ?
question.ToList().Where(X=> X.Wet ) :
question.ToList().Where(X=> X.Voice );
qq.FirstOrDefault().Dump();

Passing null as Contains() within "linq to sql" query

I have a problem with Contains in linq to sql query as below:
public IAuditRecord[] Fetch(SearchConditions searchConditions)
{
IAuditRecord[] searchedList = (from rows in _dbContex.AuditTrails
where
(searchConditions.Owner == null || searchConditions.Owner == 0) ? true : rows.Owner == searchConditions.Owner
&&
/*This line cannot compile when ActionIDs array is empty*/
(searchConditions.ActionIDs != null && searchConditions.ActionIDs.Length != 0) ? searchConditions.ActionIDs.Contains(rows.UserActionID) : true
&& ((searchConditions.StartDate != null && searchConditions.EndDate != null) ? (rows.TimeStamp >= searchConditions.StartDate && rows.TimeStamp <= searchConditions.EndDate)
: (searchConditions.StartDate != null && searchConditions.EndDate == null) ? rows.TimeStamp >= searchConditions.StartDate : (searchConditions.StartDate == null && searchConditions.EndDate != null) ? (rows.TimeStamp <= searchConditions.EndDate)
: true)
select rows).ToArray();
return searchedList;
}
This query executes perfectly if searchCondition.ActionIDs array is not null or empty,
but when i pass the ActionIDs array as null the query cannot be compiled.
So the main question is Why contains cannot work when ActionIDs array is null?
You're building an IQueryable, which defines how to query for something, not actually doing it. To do this it builds an Expression, which defines all the query intents and can later be called to actually get the data. If you were using LINQ-to-Objects, this would likely work since it would likely call searchConditions.ActionIDs != null first, then know that it doesn't have to attempt to execute the second portion. Linq-to-Entities/SQL, etc. don't have that benefit.
Long story short, you can either do:
searchConditions.ActionIDs = searchConditions.ActionIDs ?? new int[];
Or do a different query if its null, like:
var query = _dbContext.AuditTrails;
if(searchConditions.ActionIDs != null && searchCondition.ActionIDs.Length != 0)
{
query = // Further filtered query where ActionIDs are taken into account.

LINQ query does not "see" the values in array

here is my query
var traj_of_user_2=
from num in trajectoryArray
where num.ID_User == 2
select num.ID_Traj;
when i run the program, an exception appears (see the image)
what's the problem is your opinion? a friend of me told me that since the array is "lazy" there are no istances
There is a null in the array, and num.ID_User is failing. You can filter out nulls like this:
var traj_of_user_2=
from num in trajectoryArray
where num != null &&
num.ID_User == 2
select num.ID_Traj;
Only get ID_User when num != null
var traj_of_user_2=
from num in trajectoryArray
where (num != null && num.ID_User == 2)
select num.ID_Traj;

Linq with Logic

I have simple Linq statement (using EF4)
var efCars = (from d in myentity.Cars
where d.CarName == inputCar.CarName
&& d.CarIdNumber == inputCar.IdNumber
&& d.Make == inputCar.Make
select d.Car);
I want it to be smarter so that it will only query across one or more of the 3 fields IF they have values.
I can do a test before, and then have a separate linq statement for each permutation of valyes for inputcar
(i.e. one for all 3, one for if only carname has a value, one for if carname AND CarIdNumber has a value etc etc)
but there must be a smarter way
Thanks!
If "has no value" means null then you can use the null coalescing operator ?? to say take the first value if populated, otherwise take the second:
var efCars = (from d in myentity.Cars
where d.CarName == (inputCar.CarName ?? d.CarName
&& d.CarIdNumber == (inputCar.IdNumber && d.CarIdNumber)
&& d.Make == (inputCar.Make && d.Make)
select d.Car);
This basically says if a value exists it must match, otherwise treat it as matching
However if instead you're saying "when a special value (empty string) ignore it, otherwise match" then you can do one of two approaches (or possibly more!):
where (inputCar.CarName == "" || d.CarName == inputCar.CarName)
where (string.IsNullOrEmpty(inputCar.CarName) || d.CarName == inputCar.CarName)
For performance (when dealing with database queries) it can sometimes be beneficial to let EF generate queries based on the filters, instead of using one generic query. Of course you will need to profile whether it helps you in this case (never optimize prematurely), but this is how it would look if you dynamically build your query:
var efCars =
from car in myentity.Cars
select car;
if (inputCar.CarName != null)
{
efCars =
from car in efCars
where care.CarName == inputCar.CarName
select car;
}
if (inputCar.IdNumber != null)
{
efCars =
from car in efCars
where care.CarIdNumber == inputCar.IdNumber
select car;
}
if (inputCar.Make != null)
{
efCars =
from car in efCars
where care.Make == inputCar.Make
select car;
}
where (inputCar.CarName != null || d.CarName == inputCar.CarName) &&...

How do I set conditions from multiple tables in my LINQ query?

In the query below, I want to return people that meet multiple conditions. Some of the conditions apply to fields in the table containing the people to be returned. The other condition is applied to a different table (EmailAddresses) linked to the main table (People) via PersonId.
var t = People.Where(x =>
x.Type == 102 &&
x.FirstName == "Bob" &&
x.LastName == "Williams" &&
x.EmailAddresses.Where (ea=> ea.EmailAddress
== "bob.williams#acme.org")
)
.Select(x => x.PersonId)
How do I do this?
Do understand this right, at least one of them should have that adress? If yes, use the Any method:
var t = People.Where(x =>
x.Type == 102 &&
x.FirstName == "Bob" &&
x.LastName == "Williams" &&
x.EmailAddresses.Any(ea=> ea.EmailAddress
== "bob.williams#acme.org")
)
.Select(x => x.PersonId)
Any returns true if at least one of the elements of the IQueryable<T> fulfills the predicate.
I think you could do it with a join, something like this...
var t = from p in People
join e in EmailAddress on p.PersonId equals e.PersonId into pe
from a in pe.DefaultIfEmpty
where p.Type == 102 &&
p.FirstName == "Bob" &&
p.LastName == "Williams" &&
a.EmailAddress == "bob.williams#acme.org"
select p.PersonId

Resources