【问题标题】:EF Core 3.1 - Sql server IN operator translation (without AsEnumerable()/ToList())EF Core 3.1 - Sql server IN 运算符翻译(没有 AsEnumerable()/ToList())
【发布时间】:2020-11-12 07:21:30
【问题描述】:

我刚刚完成了从 EF Core 2.2 到 EF Core 3.1 的升级。我有一些这样的疑问:

...
userIdList.All(u => _context.ConversationUsers.Count(x => x.ContextOwnerCode == t.ContextOwnerCode && x.CompanyCode == u.CompanyCode && x.ConversationId == t.Id && x.UserId == u.ElementId &&
                            (x.GroupId == null || x.GroupId == 0) && (x.Deleted == null || !(bool)x.Deleted)) > 0) &&
                    _context.ConversationUsers.Count(x => x.ConversationId == t.Id && (x.GroupId == null || x.GroupId == 0) &&
                        (x.Deleted == null || !(bool)x.Deleted) && userIdList.Count(u => u.CompanyCode == x.CompanyCode && u.ElementId == x.UserId) == 0) == 0)
...

这里的 userIdList 是一个列表,需要与数据库中的数据进行比较。在 EF Core 3 中,不再翻译此函数。

一种解决方案可能是使用 AsEnumerable() 或 ToList() 但在我的情况下不是一个好的解决方案,因为我有大量数据并且不可能在客户端获取所有数据。

编辑

这是完整的查询:

var result = _context.Conversations.Where(t => t.ContextOwnerCode == contextOwnerCode &&
                ((docYear == 0 && docCode == 0) ||
                    (docYear != 0 && docCode != 0 && t.DocumentYear != null && t.DocumentCode != null && t.DocumentYear == docYear && t.DocumentCode == docCode)) &&
                (
                (senderGroup != null && senderGroup.CompanyCode > 0 && senderGroup.ElementId > 0 && recipientGroup != null && recipientGroup.CompanyCode > 0 && recipientGroup.ElementId > 0 &&
                    (userIdList == null || userListCount == 0) &&
                    t.CreatedChatGroupId != null && t.ChatGroupId != null && t.CreatedChatGroupId > 0 && t.ChatGroupId > 0 &&
                    ((senderGroup.CompanyCode == t.CreatedCompanyCode && senderGroup.ElementId == t.CreatedChatGroupId &&
                    recipientGroup.CompanyCode == t.ChatGroupCompanyCode && recipientGroup.ElementId == t.ChatGroupId) ||
                    (senderGroup.CompanyCode == t.ChatGroupCompanyCode && senderGroup.ElementId == t.ChatGroupId &&
                    recipientGroup.CompanyCode == t.CreatedCompanyCode && recipientGroup.ElementId == t.CreatedChatGroupId))) ||
                (((senderGroup != null && senderGroup.CompanyCode > 0 && senderGroup.ElementId > 0 &&
                        (recipientGroup == null || (recipientGroup.CompanyCode == 0 && recipientGroup.ElementId == 0))) ||
                    ((senderGroup == null || (senderGroup.CompanyCode == 0 && senderGroup.ElementId == 0)) &&
                        recipientGroup != null && recipientGroup.CompanyCode > 0 && recipientGroup.ElementId > 0)) &&
                    userIdList != null && userListCount > 0 &&
                    ((senderGroup != null && t.CreatedChatGroupId != null && t.ChatGroupCompanyCode == null && t.ChatGroupId == null &&
                            senderGroup.CompanyCode == t.CreatedCompanyCode && senderGroup.ElementId == t.CreatedChatGroupId) ||
                        (recipientGroup != null && t.CreatedChatGroupId == null && t.ChatGroupCompanyCode != null && t.ChatGroupId != null &&
                            recipientGroup.CompanyCode == t.ChatGroupCompanyCode && recipientGroup.ElementId == t.ChatGroupId)) &&
                    userIdList.All(u =>
                        _context.ConversationUsers.Count(x => x.ContextOwnerCode == t.ContextOwnerCode && x.CompanyCode == u.CompanyCode && x.ConversationId == t.Id && x.UserId == u.ElementId &&
                            (x.GroupId == null || x.GroupId == 0) && (x.Deleted == null || !(bool)x.Deleted)) > 0) &&
                    _context.ConversationUsers.Count(x => x.ConversationId == t.Id && (x.GroupId == null || x.GroupId == 0) &&
                        (x.Deleted == null || !(bool)x.Deleted) && userIdList.Count(u => u.CompanyCode == x.CompanyCode && u.ElementId == x.UserId) == 0) == 0) ||
                ((senderGroup == null || (senderGroup.CompanyCode == 0 && senderGroup.ElementId == 0)) &&
                    recipientGroup != null && recipientGroup.CompanyCode > 0 && recipientGroup.ElementId > 0 &&
                    (userIdList == null || userListCount == 0) &&
                    t.CreatedChatGroupId == null && t.ChatGroupCompanyCode != null && t.ChatGroupId != null &&
                    recipientGroup.CompanyCode == t.ChatGroupCompanyCode && recipientGroup.ElementId == t.ChatGroupId &&
                    _context.ConversationUsers.Count(x => x.ConversationId == t.Id && (x.GroupId == null || x.GroupId == 0) && (x.Deleted == null || !(bool)x.Deleted)) == 0) ||
                ((senderGroup == null || (senderGroup.CompanyCode == 0 && senderGroup.ElementId == 0)) &&
                    (recipientGroup == null || (recipientGroup.CompanyCode == 0 && recipientGroup.ElementId == 0)) &&
                    userIdList != null && userListCount > 1 &&
                    userIdList.All(u =>
                        _context.ConversationUsers.Count(x => x.ContextOwnerCode == t.ContextOwnerCode && x.CompanyCode == u.CompanyCode && x.ConversationId == t.Id && x.UserId == u.ElementId &&
                            (x.GroupId == null || x.GroupId == 0) && (x.Deleted == null || !(bool)x.Deleted)) > 0) &&
                    _context.ConversationUsers.Count(x => x.ConversationId == t.Id && (x.GroupId == null || x.GroupId == 0) &&
                        (x.Deleted == null || !(bool)x.Deleted) && userIdList.Count(u => u.CompanyCode == x.CompanyCode && u.ElementId == x.UserId) == 0) == 0)
                )
                ).FirstOrDefault();

【问题讨论】:

  • 我想说,如果现在不翻译,很可能以前没有。在 2.2 中,它在客户端静默执行,默认情况下导致客户端执行的查询不可翻译(并且不会像 3 中那样抛出异常)。
  • @GuruStron 我不确定 EF Core 3.x 是否能翻译 EF Core 2.2 所做的所有事情,但在这种情况下(嵌套 Count)它肯定没有并且做了客户端评估。
  • 首先,@GuruStron 写道,EF Core 2.2 很可能在尽可能多地翻译后进行客户端评估。因此,每次将Count(x) 转换为Where(x).Count(),然后将&& 上的x lambda 拆分为两个Where,然后将AsEnumerable() 放在不可翻译的部分之前,这基本上是EF Core 2.2 的功能尝试。
  • 您的代码在某处有括号不匹配,我无法翻译或弄清楚 - 请尝试更正它。
  • 我刚刚更新了完整的查询。因此,如果我理解的话,在 EF Core 2.2 中 AsEnumerable() 是隐式的,而不是在 3 中我需要指定它,无论如何,无论如何都会在客户端下载大量数据。对吗?

标签: c# linq .net-core ef-core-3.1 ef-core-3.0


【解决方案1】:

我在这里的建议是将上述查询转换为SQL Store Procedure

有一个名为LinqPad 的好工具,您可以使用它来简化转换。

附:在上面的代码中你可以尝试使用!Any(...) 方法而不是Count(...) == 0

【讨论】:

    猜你喜欢
    • 2020-04-26
    • 1970-01-01
    • 2021-03-29
    • 2020-06-15
    • 2020-09-10
    • 1970-01-01
    • 1970-01-01
    • 2012-07-11
    相关资源
    最近更新 更多