I have a linq statement that returns a list of records based on where clause
This where clause checks for two parameter values.
Out of which one parameter is optional.
so i need a suggestions if i can switch my where clause based on the optional Parameter
something like this
if(locid==0)
{
where (p.CustomerID == custid)
}
else{
where (p.CustomerID == custid) & (p.LocationID == locid )
}
can any one help me how can i get this work.
thanks
You could try writing it like this:
where (p.CustomerID == custid) && (locid == 0 || p.LocationID == locid )
Yes - queries can be composed (although you don't need this for this particular case as #rsbarro pointed out):
var query = p;
if(locid==0)
query = query.Where( p =>p.CustomerID == custid);
else
query = query.Where( p =>p.CustomerID == custid & p.LocationID == locid);
//any other conditions
As BrokenGlass mentioned, you should use composition:
IQueryable<Foo> query = unfiltered.Where(p => p.CustomerID == custId);
if (locid != 0)
{
query = query.Where(p => p.LocationID == locid);
}
Note that the query is not executed until you start reading data from it, so you needn't worry about this making multiple requests.
It looks like in your original post you were trying to use query syntax piecemeal - that won't work, but the "dot notation" is pretty simple here. You can always create your initial query using a query expression if you want - again, that query won't be executed immediately anyway.
Related
My Code :
IEnumerable<DataRow> whrRowEnum;
whrRowEnum = from r in dtInput.AsEnumerable()
where r.Field<string>("EMP_DEP") == "DEP1"
orderby EMP_DEP
select r;
The above code is working fine due to hard coded where condition, but In run-time I need to add multiple where condition in my linq query like r.Field("EMP_DEP") == "DEP1" && r.Field("EMP_ID") == "EMP1"
You can use lambda syntax to compose your query based on conditions:
IEnumerable<DataRow> query = dtInput.AsEnumerable();
if (condition1)
query = query.Where(r => r.Field<string>("EMP_DEP") == "DEP1");
if (condition2)
query = query.Where(r => r.Field<string>("EMP_ID") == "EMP1");
var whrRowEnum = query.OrderBy(r => r.Field<string>("EMP_DEP"));
Another option is adding conditions to query filter
whrRowEnum = from r in dtInput.AsEnumerable()
where (!condition1 || (r.Field<string>("EMP_DEP") == "DEP1")) &&
(!condition2 || (r.Field<string>("EMP_ID") == "EMP1"))
orderby EMP_DEP
select r;
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();
I tried to use the suggestion provided here for using In operator in linq but, i am not able to convert my requirement into LINQ statement.
Below is the SQL query which i need to convert to Linq
select *
from navigator_user_field_property
where user_id = 'albert'
and field_id in (
select field_id
from navigator_entity_field_master
where entity_id = 1
and use_type = 0)
order by field_id
I want this to be converted to a Efficient Linq.
Most of the answers deal with the predetermined list of string array which is not working in my case.
Thanks
Looks like a join to me:
var query = from navigator in db.NavigatorUserFieldProperties
where navigator.UserId == "albert"
join field in db.NavigatorEntityFieldMasters
.Where(f => f.EntityId == 1 && f.UseType == 0)
on navigator.FieldId equals field.FieldId
select navigator;
Note that this will return the same value multiple times if there are multiple fields with the same ID - but I suspect that's not the case.
You could do a more literal translation like this:
var query = from navigator in db.NavigatorUserFieldProperties
where navigator.UserId == "albert" &&
db.NavigatorEntityFieldMasters
.Where(f => f.EntityId == 1 && f.UseType == 0)
.select(f => f.FieldId)
.Contains(navigator.FieldId)
select navigator;
... and that may end up translating to the same SQL... but I'd personally go with the join.
Here is an efficient and readable LINQ query:
var fields =
from field in db.navigator_entity_field_masters
where field.entity_id == 1 && field.user_type == 0
select field;
var properties =
from property in db.navigator_user_field_properties
where property.user_id == "albert"
where fields.Contains(property.field)
select property;
Look mama!! Without joins ;-)
With Linq, can I use a conditional statement inside of a Where extension method?
var query = someList.Where(a => (someCondition)? a == "something" : true);
so, if 'someCondition' is false, 'Where' will be skipped.
Yes you can like:
var query = someList.Where(a => a == "something");
if (condition)
{
query = query.Where(b => b == "something else");
}
var result = query.ToList();
Because Where is producing an IQueryable, the execution is deferred until the ToList in my example so you can chain Wheres together as much as you want and then just execute it after you have passed all your conditions.
Make use of WhereIf extenstion method avaialbe in linq
Example
if (SearchControlMain.PostingID.HasValue)
query = query.Where(q => q.PostingID == SearchControlMain.PostingID);
instead of above go for the below
query = query.WhereIf(SearchControlMain.CategoryID.HasValue, q => q.CategoryID == SearchControlMain.CategoryID);
LINQ WhereIf Extension Method
LINQ to SQL Where Clause Optional Criteria
Not sure if this is appropriate but it is quite useful, you can use ifs quite handily with conditional where clauses:
var r = (from p in productinfo.tblproduct
where p.Accountid == accountid
select p);
if (uuf1 != null)
r = r.Where(p => p.UnitUserField1 == uuf1);
if (uuf2!= null)
r = r.Where(p => p.UnitUserField2 == uuf2);
So the where clause will be amended according to what is in UUF1 or UUF2 i.e. you might have only UUF1 with info, in which case it will take that and ignore the UUF2 where clause, you might have both in which it will take both or you might not have anything in UUF1 or 2 and your where clause will just take the accountid as the where clause.
In my case there were two "conditional" where depending on search keys, so I did:
var query = db.Package.Include("SomeThing")
.Where(item => searchString1 == null || searchString1 == "" || item.Contains(searchString1))
.Where(item => searchString2 == null || searchString2 == "" || item.Contains(searchString2));
...
from item in items
where condition1
&& (condition2 ? true : condition3)
select item
This is how can you can do it with the noob Linq syntax.
This applies the condition3 only if condition2 is false.
If condition2 is true, you are essentially doing && true which has no effect on the where clause.
So it is essentially doing this:
if(condition2)
{
from item in items
where condition1
select item
else
{
from item in items
where condition1
&& condition3
select item
}
I had a scenario like this where I had to check for null within the list itself. This is what I did.
items = from p in items
where p.property1 != null //Add other if conditions
select p;
// Use items the way you would use inside the if condition
But as Kelsey pointed out this would work too -
items = items.Where(a => a.property1 != null);
I'm not sure what the question is, but a possible answer could be:
Yes,
list.Where(item => { if (Foo(item)) return true; else return false; });
It would be a complicated way of saying something simple, though.
In my case, I wanted to keep the elements which met my criteria and log the ones that didn't without iterating multiple times.
var merchantsWithLocations = allMerchants.Where(m =>
{
if (m.Locations?.Any() != true)
{
_logger.Log("Merchant {merchantId} has no locations", m.Id);
return false;
}
return true;
};
Any time you want to do a side-effect per element (such as logging), breaking out the lambda into a statement body makes it easy to reason about.
As I'm struggling to learn LINQ I’ve managed to generate a SQL statement with "AND (0 = 1)" as part of the where clause. I'm just wondering if this result is common in poorly written queries and is a known issues to try and avoid or if I am doing something totally backwards to end up with this.
Update
public static IEnumerable<ticket> GetTickets(stDataContext db,string subgroup, bool? active)
{
var results = from p in db.tickets
where
( active == null || p.active == active )
/*(active == null ? true :
((bool)active ? p.active : !p.active))*/ &&
p.sub_unit == db.sub_units.Where(c=>subgroup.Contains(c.sub_unit_name))
select p;
return results;
}
If I ignore the active part and just run
public static IEnumerable<ticket> GetTickets1(stDataContext db,string subgroup, bool? active)
{
return db.tickets.Where(c => c.sub_unit.sub_unit_name == subgroup);
}
It returns the groups of tickets I want ignoring the active part.
I'd pull the processing out of the ternary operators.
where ( active == null || p.active == active )
EDIT
The rest of the where clause looks funky too... why is it not just doing
&& p.sub_unit.sub_unit_name == subgroup
or
&& subgroup.Contains(p.sub_unit.sub_unit_name)
?
That is some pretty heavy abuse of the ternary operator.
This expression:
(active == null ? true :
((bool)active ? p.active : !p.active))
Is equivalent to the following logic:
bool result;
if (active == null)
{
result = true;
}
else
{
if ((bool)active)
{
result = p.active;
}
else
{
result = !p.active;
}
}
result &= ...
Think carefully about what this is doing:
If active is null, you're fine, it skips to the next condition.
If active is true, result is true at the end of the conditional.
If active is false, result is false at the end of the conditional.
In the last case, the query can never return any rows!
#Tanzelax has already supplied a simple rewrite. The main idea is that you want to compare p.active to active, not actually evaluate the condition as p.active.
This is probably caused by a null value in one you the columns you have declared as non-nullable. LINQ2SQL makes all columns non-nullable by default. Go back to the designer and change the fields to allow values to be null. Unfortunately this feature is By Design (see connect.microsoft.com link below.)
(linq) incorrect sql generated for row.column == localVar when localVar is null (should be "is null" check)