我有一个奇怪的错误,就是 NullReferenceException
而使用Entity框架核心lambda语法查询数据。
使用这段代码
var usersWithRights = await _dbContext.TblUsers.Where(x => x.IsInternal).Select(x => new
{
RightIds = x.TblInternalUserRoles.FirstOrDefault().Role.TblInternalRoleRights.Select(i => i.RightId).ToList()
}).ToListAsync();
而当我应用 Count
而不是 Select
喜欢
var usersWithRights = await _dbContext.TblUsers.Where(x => x.IsInternal).Select(x => new
{
RightIds = x.TblInternalUserRoles.FirstOrDefault().Role.TblInternalRoleRights.Count
}).ToListAsync();
以上代码使用 Count
给我准确的计数结果,但我想选择的是 RightIds
. 我已经交叉检查记录存在于我的数据库中,结果当我查询使用 Count
它给我准确的结果。
我只是想问,是否有任何限制的Entity框架核心,而连接数据? 像有一个最大数量的连接允许在EF核心或我可以加入任何数量的表?
没有加入限制,但遗憾的是,EF Core查询翻译一些LINQ构造时,仍然存在很多缺点bugsissues。
通常情况下,你不需要 Include
ThenInclude
在投影(Select
)查询,因为它们被忽略了。但在这里得到NRE wo它们表明客户端评估尝试(EF Core 3.x仍然为一些构造提供客户端评估,主要是在最终投影中,比如这里),这反过来意味着翻译失败。
这里的问题似乎是
x.TblInternalUserRoles.FirstOrDefault().Role.TblInternalRoleRights.Select(i => i.RightId)
即转换序列(x.TblInternalUserRoles
)到单个元素(.FirstOrDefault()
),然后再取下序列(.Role.TblInternalRoleRights
).
工作方案是使用 SelectMany
操作符,用于平坦化源序列。FirstOrDefault()
应该去掉(对我来说毫无意义),或者如果真的需要,用相应的等价序列运算符代替。Take(1)
.
例如
RightIds = x.TblInternalUserRoles
.SelectMany(ur => ur.Role.TblInternalRoleRights.Select(i => i.RightId))
.ToList()
或
RightIds = x.TblInternalUserRoles
.SelectMany(ur => ur.Role.TblInternalRoleRights, (ur, i) => i.RightId)
.ToList()
或
RightIds = x.TblInternalUserRoles
.SelectMany(ur => ur.Role.TblInternalRoleRights)
.Select(i => i.RightId)
.ToList()