【发布时间】: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(),然后将&&上的xlambda 拆分为两个Where,然后将AsEnumerable()放在不可翻译的部分之前,这基本上是EF Core 2.2 的功能尝试。 -
您的代码在某处有括号不匹配,我无法翻译或弄清楚 - 请尝试更正它。
-
我刚刚更新了完整的查询。因此,如果我理解的话,在 EF Core 2.2 中 AsEnumerable() 是隐式的,而不是在 3 中我需要指定它,无论如何,无论如何都会在客户端下载大量数据。对吗?
标签: c# linq .net-core ef-core-3.1 ef-core-3.0