[英]Filtering on Include reverted if I perform Select afterwards in EF Core
我正在尝试在 EF Core 中使用过滤的包含,但遇到了一个我似乎无法确定具体原因的问题。
我的查询看起来像这样:
context.Users.Include(u=>u.UserRoles.Where(r => r.Role.Category == 3))
.ThenInclude(r=>r.Role).Where(u => u.userId == currentUserId)
.Select(u=> new UserDTO()
{
UserDisplayName= u.Name,
ListOfRoles = String.Join(",", u.UserRoles.Select(u => u.Role.DisplayName))
}).FirstOrDefaultAsync();
如果我从查询中省略 Select 部分并检查对象,它只填充了适当的 UserRoles,属于类别 3 的用户角色,但在检查此 Select 的结果时,它还包含属于不同的角色类别,连接到 ListOfRoles。
如果有人知道可能导致这种情况的原因,我将不胜感激。
谢谢
Include
仅适用于您返回实体的情况。 当您将投影与Select
一起使用时,您需要过滤Select
表达式中的数据:
context.Users
.Where(u => u.userId == currentUserId)
.Select(u=> new UserDTO()
{
UserDisplayName= u.Name,
ListOfRoles = String.Join(",", u.UserRoles
.Where(ur => ur.Role.Catecory == 3)
.Select(ur => ur.Role.DisplayName))
}).SingleOrDefaultAsync();
我相信 String.Join 需要在 EF Core 中进行客户端评估。 这可能会导致加载意外数据。 避免这种情况的建议是在 DTO 内执行串联,以便 Linq 查询加载原始数据并可以有效地将其转换为 SQL:
context.Users
.Where(u => u.userId == currentUserId)
.Select(u=> new UserDTO()
{
UserDisplayName= u.Name,
Roles = u.UserRoles
.Where(ur => ur.Role.Catecory == 3)
.Select(ur => ur.Role.DisplayName))
.ToList();
}).SingleOrDefaultAsync();
在 DTO 中,您将拥有:
[Serializable]
public class UserDTO
{
public string UserDisplayName { get; set; }
public IList<string> Roles { get; set; } = new List<string>();
public string ListOfRoles
{
get { return string.Join(",", Roles); }
}
}
这确保查询可以高效运行并完全转换为 SQL,然后将格式移动到 DTO。
仅当您直接选择实体时, Include
才会起作用。 进行投影(例如Select
)后, Include
被忽略。 您可以尝试在串联部分应用类别过滤:
context.Users
.Where(u => u.userId == currentUserId)
.Select(u=> new UserDTO()
{
UserDisplayName= u.Name,
ListOfRoles = String.Join(",", u.UserRoles.Where(r => r.Role.Category == 3).Select(u => u.Role.DisplayName))
})
.FirstOrDefaultAsync();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.