EF Core expression being evaluated locally... why?

c# entity-framework entity-framework-core

Question

I have a method off my db context that looks like this:

    public override async Task<IEnumerable<FeedMessage>> GetLatestFeeds(
        int userId,
        int groupId,
        int maxResults = 15,
        long lastId = 0)
    {
        if (lastId == 0) lastId = long.MaxValue;

        var userSpecific = 
            FeedMessages.Where(fm =>
                fm.UserId.HasValue && fm.UserId.Value == userId && fm.Id < lastId && !fm.IsDeleted);

        var groupSpecific = 
            FeedMessages.Where(fm =>
                fm.UserId == null && fm.GroupId.HasValue && fm.GroupId.Value == groupId && fm.Id < lastId && !fm.IsDeleted);

        var siteWide = 
            FeedMessages.Where(fm =>
                fm.UserId == null && fm.GroupId == null && fm.Id < lastId && !fm.IsDeleted);

        var feeds = await
            userSpecific.Union(groupSpecific).Union(siteWide)
                .OrderByDescending(x => x.Id)
                .Take(maxResults)
                .ToListAsync();

        return feeds.OrderBy(x => x.Id);
    }

the idea here is, I want to grab records that are user-specific, group-specific or general-purpose, organize them by ID, and return the top X results.

If I run this I get a whole screen of errors:

warn: Microsoft.EntityFrameworkCore.Query[20500]
      The LINQ expression 'Union({from FeedMessage fm in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[MySolution.Common.Entities.FeedMessage]) where ((((([fm].UserId == null) AndAlso ([fm].GroupId != null)) AndAlso (Convert([fm].GroupId, Int32) == __groupId_2)) AndAlso ([fm].Id < __lastId_3)) AndAlso Not([fm].IsDeleted)) select [fm]})' could not be translated and will be evaluated locally.
warn: Microsoft.EntityFrameworkCore.Query[20500]
      The LINQ expression 'Union({from FeedMessage fm in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[MySolution.Common.Entities.FeedMessage]) where (((([fm].UserId == null) AndAlso ([fm].GroupId == null)) AndAlso ([fm].Id < __lastId_4)) AndAlso Not([fm].IsDeleted)) select [fm]})' could not be translated and will be evaluated locally.
warn: Microsoft.EntityFrameworkCore.Query[20500]
      The LINQ expression 'Union({from FeedMessage fm in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[MySolution.Common.Entities.FeedMessage]) where ((((([fm].UserId == null) AndAlso ([fm].GroupId != null)) AndAlso (Convert([fm].GroupId, Int32) == __groupId_2)) AndAlso ([fm].Id < __lastId_3)) AndAlso Not([fm].IsDeleted)) select [fm]})' could not be translated and will be evaluated locally.
warn: Microsoft.EntityFrameworkCore.Query[20500]
      The LINQ expression 'Union({from FeedMessage fm in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[MySolution.Common.Entities.FeedMessage]) where (((([fm].UserId == null) AndAlso ([fm].GroupId == null)) AndAlso ([fm].Id < __lastId_4)) AndAlso Not([fm].IsDeleted)) select [fm]})' could not be translated and will be evaluated locally.
warn: Microsoft.EntityFrameworkCore.Query[20500]
      The LINQ expression 'orderby [x].Id desc' could not be translated and will be evaluated locally.
warn: Microsoft.EntityFrameworkCore.Query[20500]
      The LINQ expression 'Take(__p_5)' could not be translated and will be evaluated locally.

What is going on here? And how do I fix it? This is going to be a large table, evaluating locally will crush the system.

1
0
11/2/2018 12:14:37 AM

Popular Answer

I ended up making a bug report on the EF Core's github site, and several hours later I got a response I could use. It turns out that Union(), Concat(), Except(), and Intersect() are not supported for server-side operations yet. :\

That was not immediately apparent in my web searches.

Per the dev team's advice, I was able to rewrite my query like so:

return FeedMessages
    .Where(fm => fm.Id < lastId && !fm.IsDeleted && (
        (fm.UserId.HasValue && fm.UserId.Value == userId) ||
        (fm.UserId == null && fm.GroupId.HasValue && fm.GroupId.Value == groupId) ||
        (fm.UserId == null && fm.GroupId == null)))
    .OrderByDescending(x => x.Id)
    .Take(maxResults)
    .OrderBy(x => x.Id)
    .ToListAsync();

... which got me out of crisis mode, but I'd just like to throw out there to any EF Core devs watching these posts that this is important functionality and (IMO) should be prioritized as soon as realistically possible.

0
11/2/2018 10:36:24 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow