Trying to execute a WHERE IN: Invalid 'where' condition. An entity member is invoking an invalid property or method - linq

I'm trying to get a list of cases whose AccountID is found in a previous list.
The error occurs on the last line of the following:
// Gets the list of permissions for the current contact
var perms = ServiceContext.GetCaseAccessByContact(Contact).Cast<Adx_caseaccess>();
// Get the list of account IDs from the permissions list
var customerIDs = perms.Select(p => p.adx_accountid).Distinct();
// Get the list of cases that belong to any account whose ID is in the `customerID` list
var openCases = (from c in ServiceContext.IncidentSet where customerIDs.Contains(c.AccountId) select c).ToList();
I'm not sure what the "invalid property" is the error is talking about. The code compiles, I just get the error at runtime.

The problem is the CRM Linq Provider. It doesn't support all of the available options that the Linq-to-objects provider offers. In this case, the CRM does not support the Enumerable.Contains() method.
where:
The left side of the clause must be an attribute name and the
right side of the clause must be a value. You cannot set the left side
to a constant. Both the sides of the clause cannot be constants.
Supports the String functions Contains, StartsWith, EndsWith, and
Equals.
You can work around this in one of two ways:
Rework your query to use a more natural join.
If a join is not possible, you can use Dynamic Linq to generate a list of OR clauses on each item in customerIDs. This would function similarly to Enumerable.Contains.
See my answer or the accepted answer to the question "How to get all the birthdays of today?" for two separate ways to accomplish this.

Related

Lightswitch 2013 Linq queries to Get min value

I'm writing a timesheet application (Silverlight) and I'm completely stuck on getting linq queries working. I'm netw to linq and I just read, and did many examples from, a Linq book, including Linq to Objects, linq to SQl and linq to Entities.(I assume, but am not 100% sure that the latter is what Lightswitch uses). I plan to study a LOT more Linq, but just need to get this one query working.
So I have an entity called Items which lists every item in a job and it's serial no
So: Job.ID int, ID int, SerialNo long
I also have a Timesheets entity that contains shift dates, job no and start and end serial no produced
So Job.ID int, ShiftDate date, Shift int, StartNo long, EndNo long
When the user select a job from an autocomplete box, I want to look up the MAX(SerialNo) for that job in the timesheets entity. If that is null (i.e. none have been produced), I want to lookup the MIN(SerialNo) from the Items entity for that job (i.e. what's the first serial no they should produce)
I realize I need a first or default and need to specify the MIN(SerialNo) from Items as a default.
My Timesheet screen uses TimesheetProperty as it's datasource
I tried the following just to get the MAX(SerialNo) from Timesheets entity:
var maxSerialNo =
(from ts in this.DataWorkspace.SQLData.Timesheets
where ts.Job.ID == this.TimesheetProperty.Job.ID
select ts.StartNo).Min();
but I get the following errors:
Instance argument: cannot convert from 'Microsoft.LightSwitch.IDataServiceQueryable' to 'System.Collections.Generic.IEnumerable
'Microsoft.LightSwitch.IDataServiceQueryable' does not contain a definition for 'Min' and the best extension method overload 'System.Linq.Enumerable.Min(System.Collections.Generic.IEnumerable)' has some invalid arguments
I also don't get why I can't use this:
var maxSerialNo = this.DataWorkspace.SQLData.Timesheets.Min(ts => ts.StartNo);
Can anyone point me in the right direction?
Thanks
Mark
IDataServiceQueryable doesn't support full set of LINQ operator like IEnumerable has.
IDataServiceQueryable – This is a LightSwitch-specific type that allows a restricted set of “LINQ-like” operators that are remote-able to the middle-tier and ultimately issued to the database server. This interface is the core of the LightSwitch query programming model. IDataServiceQueryable has a member to execute the query, which returns results that are IEnumerable. [Reference]
Possible solution is, execute your query first to get collection of type IEnumerable by calling .ToList(), then you can call .Min() against the first query result. But that isn't good idea if you have large amount of data, because .ToList() will retrieve all data match the query and do further processing in client side, which is inefficient.
Another way is, change your query using only operators supported by IDataServiceQueryable to avoid retrieving unnecessary data to client. For example, to get minimum StartNo you can try to use orderby descending then get the first data instead of using .Min() operator :
var minStartNo =
(
from ts in this.DataWorkspace.SQLData.Timesheets
where ts.Job.ID == this.TimesheetProperty.Job.ID
orderby ts.StartNo descending select ts
).FirstOrDefault();

Concatenating a LINQ query and LINQ sort statement

I'm having a problem joining two LINQ queries.
Currently, my (original) code looks like this
s.AnimalTypes.Sort((x, y) => string.Compare(x.Type, y.Type));
What I'm needing to do is change this based on a date, then select all data past that date, so I have
s.AnimalTypes.Select(t=>t.DateChanged > dateIn).ToList()
s.AnimalTypes.Sort((…
This doesn't look right as it's not sorting the data selected, rather sorting everything in s.AnimalTypes.
Is there a way to concatenate the two LINQ lines? I've tried
s.AnimalTypes.Select(t=>t.DateChanged > dateIn).ToList().Sort((…
but this gives me an error on the Sort section.
Is there a simple way to do this? I've looked around and Grouo and OrderBy keep cropping up, but I'm not sure these are what I need here.
Thanks
From your description, I believe you want something like:
var results = s.AnimalTypes.Where(t => t.DateChanged > dateIn).OrderBy(t => t.Type);
You can call ToList() to convert to a List<T> at the end if required.
There are a couple of fundamental concepts I believe you are missing here -
First, unlike List<T>.Sort, the LINQ extension methods don't change the original collections, but rather return a new IEnumerable<T> with the filtered or sorted results. This means you always need to assign something to the return value (hence my var results = above).
Second, Select performs a mapping operation - transforming the data from one form to another. For example, you could use it to extract out the DateChanged (Select(t => t.DateChanged)), but this would give you an enumeration of dates, not the original animal types. In order to filter or restrict the list with a predicate (criteria), you'd use Where instead.
Finally, you can use OrderBy to reorder the resulting enumerable.
You are using Select when you actually want to use Where.
Select is a projection from one a collection of one type into another type - you won't increase or reduce the number of items in a collection using Select, but you can instead select each object's name or some other property.
Where is what you would use to filter a collection based on a boolean predicate.

Linq match item in lookup column with multiple entries

I have list A that has a lookup to list B that allows multiple entries. One A to multiple related Bs - standard practice. I want to find A where B contains a reference to a particular instance of 'b'.
I've tried:
var As = from a in ARecs where a.Bs.Contains(b) select a;
But I get the usual 'multiple tables involved' error. How do I go about this please?
thanks in advance
the error I'm getting is "The query uses unsupported elements, such as references to more than one list, or the projection of a complete entity by using EntityRef/EntitySet."
The A and B list code is generated by SPMetal if that makes any difference
Some LINQ cannot be turned into CAML (did I forget to mention this was on SPMetal generated LINQ to Sharepoint - doh!) and needs to be performed as 2 queries - the first ToList then the 2nd on that list. This worked for me.
Var Bs = A.ToList().Where(record => record.Bs.Contains(b))

Shaping EF LINQ Query Results Using Multi-Table Includes

I have a simple LINQ EF query below using the method syntax. I'm using my Include statement to join four tables: Event and Doc are the two main tables, EventDoc is a many-to-many link table, and DocUsage is a lookup table.
My challenge is that I'd like to shape my results by only selecting specific columns from each of the four tables. But, the compiler is giving a compiler is giving me the following error:
'System.Data.Objects.DataClasses.EntityCollection does not contain a definition for "Doc' and no extension method 'Doc' accepting a first argument of type 'System.Data.Objects.DataClasses.EntityCollection' could be found.
I'm sure this is something easy but I'm not figuring it out. I haven't been able to find an example of someone using the multi-table include but also shaping the projection.
Thx,Mark
var qry= context.Event
.Include("EventDoc.Doc.DocUsage")
.Select(n => new
{
n.EventDate,
n.EventDoc.Doc.Filename, //<=COMPILER ERROR HERE
n.EventDoc.Doc.DocUsage.Usage
})
.ToList();
EventDoc ed;
Doc d = ed.Doc; //<=NO COMPILER ERROR SO I KNOW MY MODEL'S CORRECT
DocUsage du = d.DocUsage;
Very difficult to know what is going on without a screencap of your model, including the navigational properties on each entity.
But if your saying it's a many-to-many between Event and Doc (with EventDoc being the join table), and assuming your join table has nothing but the FK's and therefore doesn't need to be mapped, then shouldn't a single Event have many Doc's?
This query:
var query = ctx.Event.Include("EventDoc.Doc");
Would imply (based on the lack of pluralization): a single Event has a single EventDoc which has a single Doc.
But shouldn't that be: a single Event has a single EventDoc which has many Doc's.
Therefore your projection doesn't really make sense. Your trying to project to an anonymous type, with EventDate and Filename for a single Doc, but an Event has many Docs.
Maybe a projection like this would be more suitable:
var query = ctx.Event.Include("EventDoc.Docs.DocUsage")
.Select(x => new
{
EventDate = x.EventDate,
DocsForEvent = x.EventDocs.Docs
}).ToList();
And for that you work you need to fix up your model. Im surprised it even validates/compiles.
Either your model is wrong or your description of the database cardinalities in your question is. :)
Of course, i could be completely misunderstanding your database and/or model - so if i am let me know and i'll remove this answer.

Linq-to-sql Not Contains or Not in?

I'm building a poll widget. I've 2 tables, call them Polls and PollsCompleted. I need to do a linq query to get all the Polls that do not exist for a given user in PollsCompleted.
I have the following sets:
For Polls
Where Active == True
For PollsCompleted
Where UserId == ThisUserId
Where PollId = Polls.Id
Now I need to get all Polls that do not exist in PollsCompleted. I need an example for this using either a single or multiple queries. I've tried to break it down into 2 queries.
Basically, I've 2 IQueryables of type T and T1. I want to take all T's where T.ID does not exist in T1.ParentId.
T.Where(x => ! T1.Select(y => y.ParentID).Contains(x.ID))
In Linq you often work from the bottom up. Here we first get a collection of all the parentIDs in T1 -- the T1.Select(...) part. Then we create a where clause that selects all of the Ts whose IDs are not contained in that set.
Note that the result is a query. To materialize it, use ToList() or similar on the statement above.
Use Except. That will work in this case.
For your reference Enumerable.Except Method

Resources