【问题标题】:EF Core distinct by columnEF Core 按列区分
【发布时间】:2020-12-01 00:52:51
【问题描述】:

在 EF 6 中,如果我想通过不同的姓氏来选择用户,我可以这样做:

var users = _context.User
            .GroupBy(x => x.LastName)
            .Select(x => x.FirstOrDefault())
            .OrderBy(x => x.LastName)
            .Take(10)
            .ToList();

在 EF Core 3.1.6 中,同样的查询给了我以下异常:

System.InvalidOperationException: The LINQ expression '(GroupByShaperExpression:
KeySelector: (u.LastName), 
ElementSelector:(EntityShaperExpression: 
    EntityType: User
    ValueBufferExpression: 
        (ProjectionBindingExpression: EmptyProjectionMember)
    IsNullable: False
)
)
    .FirstOrDefault()' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync()

有没有什么方法可以在不使用 AsEnumerable(或其他替代方法)的情况下使用该查询,这会将整个巨大的表加载到内存中?我在下面使用的数据库是 Microsoft SQL Server 2014,它可以处理这种查询。

【问题讨论】:

    标签: c# sql-server entity-framework entity-framework-core


    【解决方案1】:

    EF Core 5 可能会支持这种类型的查询(在 EF Core GitHub 存储库中肯定存在未解决的问题)。

    EF Core 3.x 中的解决方法类似于How to select top N rows for each group in a Entity Framework GroupBy with EF 3.1 - (1) 使用子查询来选择不同的键值,(2) 然后将其与结合限制运算符的主查询联接/关联(在此案例,Take(1)):

    var users = _context.User.Select(x => x.LastName).Distinct() // (1)
        .SelectMany(key => _context.User.Where(x => x.LastName == key).Take(1)) // (2)
        // the rest is the same as the origonal
        .OrderBy(x => x.LastName)
        .Take(10)
        .ToList();
    

    【讨论】:

    • 这不是很可怕吗?甚至 LINQ-to-SQL 也能正确翻译它!变通办法已经够花哨了,但这样的限制会让许多开发人员望而却步。好吧,你知道这一切。一个值得一提的缺点是,投影仍然会选择子查询中的整条记录,并且只会影响主查询的字段列表。除非您愿意在子查询中重复投影(包括分组键)。叹息……
    • @Gert 有趣(或悲伤?)的事情是SelectMany 生成的连接子查询使用ROW_NUMBER() OVER(PARTITION BY ... 结合where row <= 1,这是前N 个项目所需的精确翻译的一组。根本不需要不同的部分。但是对于生成 3 个自连接以包含映射到同一个表的单个字段的人该怎么说 :-( 他们在 EF6 上做了很多好事/改进,同时非常愚蠢/奇怪的事情,并希望人们投票将它们“修复”为“增强”/功能而不是错误修复:-/
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-13
    • 2019-08-07
    • 2020-04-18
    • 1970-01-01
    • 2022-02-27
    • 2021-05-11
    相关资源
    最近更新 更多