Can't translate method into a store expression [duplicate] - c#

This question already has an answer here:
Method cannot be translated into a store expression
(1 answer)
Closed 7 years ago.
The closest to my questions that I've found is this one and as far I can see, it's not regarding the same issue. I might be mistaken, in which case, I hope someone can explain how the similarity goes (except for the same words referring to the error, that is). With that being said, I have the following issue.
This works as supposed to.
List<Typo> things = context.Things.Where(thing => thing.Nice).ToList();
This, however, doesn't.
List<Typo> things = context.Things.Where(thing => IsNice(thing)).ToList();
...
private bool IsNice(Typo thing) { return thing.Nice; }
context is of type ModelContainer deriving DbContext. I've been told that it's a standard setup for EF and I have no reason to suspect otherwise. The error message claims the following.
{"LINQ to Entities does not recognize the method XXX method, and this method cannot be translated into a store expression."}
I have no experience with this error and, frankly, the research I've made gave me very little clarity. What can I look into to (a) make it work my way and (b) investigate it further.

You can't use your own method in a lambda expression of Linq to Entities, even if it only encapsulates your entities properties because Linq to Entities doesn't know how to translate them into a valid SQL statement.
For getting your methods working you must get the entities from the database with a valid LinQ to Entities query and fill with them a C# collection (like a List). You can use the extension methods .AsEnumerable(), .ToList(), Select(), ...
Here you have a list of .NET methods that LinQ to Entities can translate and you can use in your lambda expression, also with a brief explanation of your exception:
CLR Method to Canonical Function Mapping
And here you have a list with the LinQ methods supported by LinQ to Entities:
Supported LinQ methods

IMO, it's still the same issue as the question you mention: LINQ to Entities cannot interpret IsNice, and thus, you need 'normal' LINQ to resolve the Where method. You can force this with the AsEnumberable method:
List<Typo> things = context.Things.AsEnumerable().Where(thing => IsNice(thing)).ToList();
Or even shorter.
List<Typo> things = context.Things.Where(IsNice).ToList();

Related

LINQ to Entities does not recognize the method 'System.Collections.Generic.IEnumerable`1

I am getting this error while using this IEquality comparer for intersection.
Can somebody identify where I am doing it wrong?
Pleas ask if you need more information.
When you write LINQ to Entities, you must remember that eventually all of your LINQ expression is translated to SQL. So for every method call you make in that expression, you should think if there's a reasonable way to translate it to SQL.
Having that in mind, you can see that:
SQL has no notion of .ToList(), which is probably the source of your current error. calls to .ToList() should be made at the end of the expression, as a way to "materialize" the query (i.e. make EF make the actual call to the database and return results).
Your database knows nothing about C# interfaces. You can't expect any implementation of IEqualityComparer to be translatable to SQL.
As #Dai has noted, you seem to be using too many joins. Make sure your model has the right navigation properties between entities, and use them.

What am I using? (Linq/sql) [duplicate]

This question already has answers here:
Linq query or Lambda expression?
(5 answers)
Closed 7 years ago.
My project currently uses for following syntax for "linq"
var le = domainModel.EntityDataContext.Table_name_here.Query()
.WithFullReadCheck(domainModel.Security)
.Where(x => x.Metadata.AdvisorID == advisorId).FirstOrDefault();
It is said the above code is linq, being unaware about linq I decided to learn it. However, on https://msdn.microsoft.com/en-us/library/gg509017.aspx , things are pretty different.
what is being used in my code? Is it a version of linq? Is it something else?
What you are using is LINQ. There are 2 different notations you can use for writing LINQ - Lambda Syntax and Query Syntax
The difference is explained here: LINQ: Dot Notation vs Query Expression
There is more information on this on MSDN here: https://msdn.microsoft.com/en-us/library/bb308959.aspx
The MSDN articles starts explaining LINQ with SQL-like syntax ("query syntax") and then goes on to explain Lambda Expressions and Expression Trees ("lamba syntax").
That is extension method syntax for a query. The .Query().WithFullReadCheck() are much less common, but the rest .Where and .FirstOrDefault are pretty common query extensions. LINQ is a special syntax for expressing the same thing that can be done with chaining the query extension methods. Behind the scenes, they are identical.
See this question which gives an example of both LINQ and extension method syntax and has a good discussion of the differences between them: Extension methods syntax vs query syntax
Linq (language integrated query) is the language you use to query the data. You don't care where do they come from, that's the whole point of using it. You can use the same code to query arrays, collections, databases, xml files, directories, whatever... Linq translates your code in the background, so if you use it for instance to get the data from a database, it produces SQL to be sent to the database.
There are two syntax versions available:
1.) lambda syntax
2.) chainable methods
It doesn't matter which one you chose, just try to be consistent with it and use what makes you more comfortable / makes more sense in your situation.
LINQ is 'Language INtegrated Query'. In practical terms it means two things to most people:
The way that inline delegates are converted by the compiler into expression trees, not anonymous methods. That means that x => x.Metadata.AdvisorID == advisorId is not compiled into IL at compile time: instead it's compiled into code which builds an equivalent Expression object, which can be passed to a provider such as Entity Framework or LINQ to SQL, in order to generate a database query.
The other part it means to most people is the so-called "syntactic sugar", which effectively calls .Where(), .OrderBy() etc on your behalf:
from a in something
where a.Name == "Bob"
select a;
In both cases, the Queryable class in .NET provides extension methods for building a chain of Expression objects, for example .Where(), .OrderBy(), .Select() etc - these take an IQueryable (either untyped or with a generic parameter) and return another. They lightly wrap an Expression object at each point which represents the query as a whole.
Meaning:
someQueryable.Where(x => x.Id > 3).OrderBy(x => x.Date).Select(x => x.Ref)
Returns an object implementing IQueryable which holds an Expression which looks like:
Select(OrderBy(Where(someQueryable, x => x.Id > 3), x => x.Date), x => x.Ref)
... which is readable by LINQ providers to produce something like:
SELECT Ref FROM someTable WHERE Id > 3 ORDER BY Date
Finally, note that .Where(), .OrderBy() and the like are NOT limited to queryable/LINQ objects. They exist for IEnumerable (and IEnumerable<>), too - but this is not LINQ, and simply performs the operations at the instant that the method is called.

Implicit AsQueryable

The following linq2entities code would appear to call the IEnumerable version of FirstOrDefault extension, because PersonHistories is an ICollection. At runtime however, it actually calls the IQueryable version.
var test = db.Persons.Where(d => d.PersonKey == 4)
.Select(f => f.PersonHistories.FirstOrDefault());
The problem I am having is the custom query provider I am using does not perform this automatic conversion, and I get the error "...ICollection cannot be used for parameter of type IQueryable". Thus requires explicitly calling AsQueryable to work around this, but for complex queries it gets very redundant and not feeling very DRY:
db.Persons.Where(d => d.PersonKey == 4)
.Select(f => f.PersonHistories.AsQueryable().FirstOrDefault());
I have dug around in the framework reference source trying to find the Linq 2 Entities visitors/provider stuff, but have had no luck(perhaps is not part of any of the open reference sources). How do the base providers accomplish this implicit use of AsQueryable?
I do understand that these are translated to expression trees.
I do understand that the Enumerable.FirstOrDefault is replaced with Queryable.FirstOrDefault by the provider. That is the premise of the question.
How do the base providers accomplish this implicit use of AsQueryable?
They don't. Your code doesn't really execute FirstOrDefault() at all. It builds an expression tree which represents the call, but that isn't executed directly. The query provider sees that, works out that the f.PersonHistories is actually based on an entity which is in the database, and converts the query appropriately.

Linq to entities : Unions + Distinct

I don't know how I can do several union with a distinct.
When I use .Distinct with an IEqualityComparer an exception in threw :
LINQ to Entities does not recognize the method 'System.Linq.IQueryable'
My code is
var union = query.Union(query1).Union(query2);
union = union.Distinct(new EqualityComparerTransaction());
LINQ to Entities does not support the overload of Distinct which takes an IEqualityComparer. When you think about it, it really can't, because LINQ to Entities queries will be converted to SQL, and you cannot convert an interface reference to SQL.
Therefore, you must either:
Use the overload of Distinct which does not take any compare, or
Bring both lists into object space and do the Distinct in LINQ to Objects, like this:
var union = query.Union(query1).Union(query2);
union = union.AsEnumerable().Distinct(new EqualityComparerTransaction());
Naturally, the risk here is that you might bring too many records back from the DB server. You could also use both of these techniques in order to do a portion of the comparison on the server and another portion in object space.
The question answered but I just want to share my experience.
Not sure but I think the error message goes with saying Distinct method not supported with this argument I think.
In fact we just want Linq to SQL , a queryable expression that says if this properties same get one of them.
But when we use a class such as EqualityComparerTransaction it can't be translated to sql normally.
There is an another method GetDistict < T >(string propertyName) But sadly it doesn't work as we expected. This method also goes to DB(what else our source) and get some data and evaluate distinct.
If GetDistinct(string propertyName) extention method were do sql convertion operation It could be. But there is no way.
Sadly the single way of doing that is coding your own distinct extention for LINQ_TO_SQL.I don't think it will be easy! So Enumarating data on the server side seems easiest for now.

Error, method not supported by LINQ to Entities

Why I am getting this error:
The method 'Single' is not supported by LINQ to Entities. Consider using the method 'First' instead.
public ActionResult Details(int id)
Line 27: {
var result = (from d in _db.MovieSet
Line 29: where d.Id == id
Line 30: select d).Single();
//
//
}
Code compiles safe, but only breaks if call is made to the respective section. I am new to LINQ, therefore do not know which methods are for LINQtoSQL or LINQtoEntities. This means more errors! We cannot remember all methods this way.
My question is, if there are limitations to the methods applicable to certain types / scenarios, why do they appear in Intellisense?
EDIT: Any work-around / technique helpful to have an idea if one is supported ?
Microsoft has a complete list of supported and unsupported methods in Linq to Entities. That's where to go to find out this information.
You'll notice that the Single and SingleOrDefault methods are in fact listed as "not supported" in the section on Paging Methods.
As Jared pointed out, the compiler does not know at compile time which provider you are using, so it has no way to enforce compile-time safety of extension methods that the provider may or may not implement. You'll have to rely on the documentation instead.
In the case of LINQtoSQL / Entities, the queries are all broken down into expression trees which are then passed to the provider APIs. The providers cannot provide compile time information about the trees they do or do not support because there is no syntactic difference. The only choice is for them to provide runtime data.
For example once in expression tree form, both the Single and First appear as a MethodCallExpression instance.
Unfortunately, it's yet another indication of both the relative immaturity of EF and the Object Relational Impedance Mismatch.
Documentation is your friend if you choose to go this route.

Categories

Resources