I'm migrating some stuff from one mysql server to a sql server but i can't figure out how to make this code work:
using (var context = new Context())
{
...
foreach (var item in collection)
{
IQueryable<entity> pages = from p in context.pages
where p.Serial == item.Key.ToString()
select p;
foreach (var page in pages)
{
DataManager.AddPageToDocument(page, item.Value);
}
}
Console.WriteLine("Done!");
Console.Read();
}
When it enters into the second foreach (var page in pages)
it throws an exception saying:
LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression.
Anyone know why this happens?
If you really want to type
ToString
inside your query, you could write an expression tree visitor that rewrites the call toToString
with a call to the appropriateStringConvert
function:I got the same error in this case:
After spending way too much time debugging, I figured out that error appeared in the logic expression.
The first line
search.Contains(log.Id.ToString())
does work fine, but the last line that deals with a DateTime object made it fail miserably:Remove the problematic line and problem solved.
I do not fully understand why, but it seems as ToString() is a LINQ expression for strings, but not for Entities. LINQ for Entities deals with database queries like SQL, and SQL has no notion of ToString(). As such, we can not throw ToString() into a .Where() clause.
But how then does the first line work? Instead of ToString(), SQL have
CAST
andCONVERT
, so my best guess so far is that linq for entities uses that in some simple cases. DateTime objects are not always found to be so simple...Just save the string to a temp variable and then use that in your expression:
The problem arises because
ToString()
isn't really executed, it is turned into a MethodGroup and then parsed and translated to SQL. Since there is noToString()
equivalent, the expression fails.Note:
Make sure you also check out Alex's answer regarding the
SqlFunctions
helper class that was added later. In many cases it can eliminate the need for the temporary variable.Cast table to
Enumerable
, then you call LINQ methods with usingToString()
method inside:But be careful, when you calling
AsEnumerable
orToList
methods because you will request all data from all entity before this method. In my case above I read alltable_name
rows by one request.Upgrading to Entity Framework Version 6.2.0 worked for me.
I was previously on Version 6.0.0.
Hope this helps,