linq query not working - linq

I have the following query:
var req= (from tl in resultlist
where (tl.Message.StartsWith("Do not return") && tl.Type == "Int") &&
(tl.Note.StartsWith("Do no return") && tl.Type == "Ext")
select tl).Any();
I am trying to see if there are records where Message starts with "Do not return" and Type is "Int"
and there is another message where Note start with "Do no return" and Type is "Ext".
Seems like my query is wrong as not returning anything.

You probably want to change that && to a || as one of the comments (Joachim Isaksson) above points out. You are asking for a property (.Type) to exist in 2 different ways on one entity. That is not possible.
Try
req= (from tl in resultlist
where (tl.Message.StartsWith("Do not return") && tl.Type == "Int") ||
(tl.Note.StartsWith("Do no return") && tl.Type == "Ext")
select tl).Any();

var intMessages = from tl in resultlist
where tl.Message.StartsWith("Do not return")
&& tl.Type == "Int"
select tl;
var extMessages = from tl in resultlist
where tl.Message.StartsWith("Do not return")
&& tl.Type == "Ext"
select tl;
var intAndExtMessages = intMessages.Any() && extMessages.Any();
This will ensure that in the result set there are some "Do not return" messages which start with "Int" AND in the same result set are some other messages which start with "Ext"
The function (the condition in query) checks if the source element meets some requirements so if you check for the same object's Type to be "Int" and "Ext" is not possible, since can't have two string values in the same time.
On the other hand you need to find out if in the resultlist exist items of two different types or for two exclusive conditions, so this it can't be done in a single iteration (each LINQ query is an iterator in the end..).

Related

Add a Contains("string") functionality Azure Table LINQpad query?

OK, this doesn't work due to Azure Table query subset constraints:
var res = tcmarketnlog.Where(t => t.Level == level && t.Message.Contains("151207151510") && t.Timestamp >= start && t.Timestamp <= end).Take(1000);
The t.Message.Contains("151207151510") bombs. However, there must be some way to then search the results in LINQpad and select only the results with this string in the message.
For example, I could not coerce the result into a variable that was then queriable again with LINQ. Any tips?
If you can't use string.Contains on an Azure Table Queryable, you can still turn it into an Enumerable and then apply the additional filter to only show the results you want. However, it means that it will return all records that meet the other criteria over the network before then limiting them on the client side to only those rows where the Message field contains the specified string.
var res = tcmarketnlog.Where(t => t.Level == level && t.Timestamp >= start && t.Timestamp <= end).AsEnumerable().Where(t => t.Message.Contains("151207151510")).Take(1000);
Maybe message is null. Just check message null before contains. pls try this:
var res = tcmarketnlog.Where(t => t.Level == level
&& t.Message != null && t.Message.Contains("151207151510")
&& t.Timestamp >= start && t.Timestamp <= end).Take(1000);

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();

LINQ Error The type is not supported in aggregation operations

I have LINQ code and I receive the following error: System.ServiceModel.FaultException: The type 'ObjectMgmt' is not supported in aggregation operations.
(from cinnost in edc.CinnostSOPs
where cinnost.LegislativneVyznamna == true &&
cinnost.ObjektId == objektid
select (from o in edc.PlanRealizaces
where o.CinnostSOPIdSOP == cinnost.IdSOP &&
o.DatumPlatnosti <= DateTime.Now &&
o.Provest == true &&
o.DatumProvedeni == null
orderby o.DatumPlatnosti descending
select new ObjectMgmt
{
Datum = (DateTime.Now.Date - o.DatumPlatnosti.Value).TotalDays
}).Max(m => m)).ToList<ObjectMgmt>();
The message speaks of an aggregate. The only aggregate I see is the Max call. This is the hint needed to debug the problem.
You care calculating the max of a sequence of ObjectMgmt instances which is obviously not possible. Change that to what you really meant.
The compiler error you get tells you that ObjectMgmt can not be used as the source of an aggregation. This happens because Max requires that the ObjectMgmt type implements IComparable.
After formatting your query to make it more readable it seems that you want to find the ObjectMgmt instance where Datum has the maximum value.
Since you already ordered the values descending by DatumPlatnosti you know that the ObjectMgmt instances are ordered by increasing Datum values. Therefore you don't need an aggregation at all. Just take the last element of the sequence (I would however order ascending and then take the first element).
(from cinnost in edc.CinnostSOPs
where cinnost.LegislativneVyznamna == true &&
cinnost.ObjektId == objektid
select (from o in edc.PlanRealizaces
where o.CinnostSOPIdSOP == cinnost.IdSOP &&
o.DatumPlatnosti <= DateTime.Now &&
o.Provest == true &&
o.DatumProvedeni == null
orderby o.DatumPlatnosti
select new ObjectMgmt
{
Datum = (DateTime.Now.Date - o.DatumPlatnosti.Value).TotalDays
}).First()).ToList<ObjectMgmt>();
Because your ObjectMgmt objects have only one property filled by query: Datum, change your Max call to get max of Datum, not the ObjectMgmt itself:
(from cinnost in edc.CinnostSOPs
where cinnost.LegislativneVyznamna == true &&
cinnost.ObjektId == objektid
select (from o in edc.PlanRealizaces
where o.CinnostSOPIdSOP == cinnost.IdSOP &&
o.DatumPlatnosti <= DateTime.Now &&
o.Provest == true &&
o.DatumProvedeni == null
orderby o.DatumPlatnosti descending
select new ObjectMgmt
{
Datum = (DateTime.Now.Date - o.DatumPlatnosti.Value).TotalDays
}).Max(m => m.Datum)).ToList<ObjectMgmt>();

How can I check for null values in this linq query where clause

I have a linq query to locate a matching item in a SharePoint library. It works fine if there is a custom property called 'MMSTerm' but if the property is null then obviously my string modifications will fail and error out when it hits x["MMSTerm"]
I will need to use string.replace in my where operation so a null won't be good.
SPListItem item = (from x in Items.OfType<SPListItem>()
where x["MMSTerm"].ToString() == pageReference.ToString()
select x).ToList<SPListItem>().FirstOrDefault();
Hopefully this is an easy one.
You can verify if field exists with SPFieldCollection.ContainsField method
SPListItem item = (from x in Items.OfType<SPListItem>()
where x.Fields.ContainsField("MMSTerm") &&
(x["MMSTerm"] == null ||
x["MMSTerm"].ToString() == pageReference.ToString())
select x).FirstOrDefault();
Also I think fluent API looks better in this case:
SPListItem item = Items.OfType<SPListItem>()
.FirstOrDefault(x =>
x.Fields.ContainsField("MMSTerm") &&
(x["MMSTerm"] == null ||
x["MMSTerm"].ToString() == pageReference.ToString()));
Since calling x["MMSTerm"] throws an exception when "MMSTerm" does not exist, rather than returning null, you should call ContainsField
x.Fields.ContainsField("MMSTerm")
to see if the field is there:
SPListItem item = (from x in Items.OfType<SPListItem>()
where x.Fields.ContainsField("MMSTerm") && x["MMSTerm"].ToString() == pageReference.ToString()
select x).FirstOrDefault();
Since && short-circuits evaluation when x.Fields.Contains("MMSTerm") is false, the x["MMSTerm"] would not be evaluated.
In case the x["MMSTerm"] could contain nulls, you could use the ""+obj trick to avoid null reference exceptions:
var pageRefStr = pageReference.ToString();
SPListItem item = (from x in Items.OfType<SPListItem>()
where x.Fields.ContainsField("MMSTerm") && pageRefStr.Equals(""+x["MMSTerm"])
select x).FirstOrDefault();

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) &&...

Resources