Search code examples
c#linq.net-coreef-core-3.1

TakeWhile fails for unapparent reason


In my following Linq query, that I run against a SQL Server 2012 instance, I attempt to read the most recent records up to the previously established MasterId marker (which is a Guid).

var cdc = crm.CdcContacts
             .Include("CdcMaster")
             .OrderByDescending(x => x.CreatedOn)
             .TakeWhile(x => x.MasterId != marker)
             .OrderBy(x => x.CreatedOn);

However, this fails.

"Processing of the LINQ expression 'DbSet\r\n
.OrderByDescending(x => x.CreatedOn)\r\n .TakeWhile(x => x.Id != new Guid(\"ABFF5734-F59F-EA11-80CB-005056BC5333\"))' by 'NavigationExpandingExpressionVisitor' failed. This may indicate either a bug or a limitation in EF Core. See https://go.microsoft.com/fwlink/?linkid=2101433 for more detailed information."

The link in the error message leads to the page on Client vs. Server evaluation so I'm pretty sure the TakeWhile can't be evaluated - I know the cursor logic doesn't work in the same way in older versions of SQL Server, perhaps this could be an explanation.

When I replace the TakeWhile with a simple Take(10), everything works - this evaluates neatly as SELECT TOP 10 * but I get no output of the generated SQL through the console logger factory before the exception hits.

Can someone help me understand what possible reasons might exist for this TakeWhile to not work?


Solution

  • This exception indicates unsupported LINQ method.

    I wish EF Core provided documentation with list of supported / unsupported LINQ methods (and CLR properties/methods) like EF6, but up to now they didn't, so it's trial and error.

    But TakeWhile and SkipWhile definitely are one of unsupported (and I'm guess they'll never be). I'm not sure why Queryable contains them at all - probably for compatibility with Enumerable methods. But AFAIK no query provider (except LINQ to Object of course) does implement them, since they have no natural translation to SQL.

    You can of course switch to Enumerable methods (with AsEnumerable() as explained in the link), but that's not good in general. You'd better express your query with other standard LINQ operators.


    P.S. The database and EF Core database provider doesn't matter - the aforementioned methods are not supported by EF Core LINQ query processor.