简体   繁体   中英

EF Core expression being evaluated locally… why?

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM