EF Core 3.1 查询导致在 Include 中使用的 InvalidOperationException Lambda 表达式无效
EF Core 3.1 Query results in an InvalidOperationException Lambda expression used inside Include is not valid
为什么这个 EF Core 3.1 典型查询会导致:
System.InvalidOperationException: Lambda expression used inside
Include is not valid.
(注意:IgnoreQueryFilters() 不是这里的问题。即使没有它,也会导致相同的错误)
var tenant = await context.Tenants.IgnoreQueryFilters()
.Include(i => i.Locations).ThenInclude(x => x.CurrentResidents.DefaultIfEmpty()).IgnoreQueryFilters()
.Include(i => i.Locations).ThenInclude(x => x.DefaultResidents.DefaultIfEmpty()).IgnoreQueryFilters()
.Where(l => l.Id == tenantId)
.FirstOrDefaultAsync()
.ConfigureAwait(false);
这是我的 sql 对我要实现的目标的解释:
select t.* from tenants
left join locations l on l.TenantId = t.Id
left join residents c on c.CurrentLocationId = l.Id
left join residents d on d.DefaultLocationId = l.Id
where t.Id = @tenantId
请帮忙。 :祈祷:
您的问题包含 Locations
两次。不确定您 SQL 您要检索的内容。 CurrentLocationId
AND DefaultLocationId
匹配 LocationId
的居民?然后在 LINQ 语句中使用 AND。
如果是其他情况,那么 CurrentResidents 和 DefaultResidents 的类型是什么?相同 Resident
类型?那么你可能想要两套...
请提供更多信息...
正如 Felix 指出的那样,问题是您两次包含位置,这在 ef 核心中是不正确的。以下是实现此目标的方法:
var tenant = await context.Tenants
.IgnoreQueryFilters()
.Include(i => i.Locations.CurrentResidents.DefaultIfEmpty())
.Include(i => i.Locations.DefaultResidents.DefaultIfEmpty())
.FirstOrDefaultAsync(l => l.Id == tenantId, cancellationToken)
.ConfigureAwait(false);
调用一次 IgnoreQueryFilters 就足够了,你不需要调用它 3 次。
调用 where 和 first 或 default 是不必要的。您可以只使用第一个或默认的 lambda。
这就是我要找的东西:
var tenant = await context.Tenants
.IgnoreQueryFilters()
.Include(i => i.Locations).ThenInclude(x => x.CurrentResidents)
.Include(i => i.Locations).ThenInclude(x => x.CurrentResidents)
.FirstOrDefaultAsync(l => l.Id == tenantId)
.ConfigureAwait(false);
Sql 由 ef core 生成有点奇怪,但会产生我感兴趣的结果,所以一切都很好。
@bencel:感谢您指出这些问题。我专注于获取查询 运行,所以忽略了那些。
谢谢大家!!
为什么这个 EF Core 3.1 典型查询会导致:
System.InvalidOperationException: Lambda expression used inside Include is not valid.
(注意:IgnoreQueryFilters() 不是这里的问题。即使没有它,也会导致相同的错误)
var tenant = await context.Tenants.IgnoreQueryFilters()
.Include(i => i.Locations).ThenInclude(x => x.CurrentResidents.DefaultIfEmpty()).IgnoreQueryFilters()
.Include(i => i.Locations).ThenInclude(x => x.DefaultResidents.DefaultIfEmpty()).IgnoreQueryFilters()
.Where(l => l.Id == tenantId)
.FirstOrDefaultAsync()
.ConfigureAwait(false);
这是我的 sql 对我要实现的目标的解释:
select t.* from tenants
left join locations l on l.TenantId = t.Id
left join residents c on c.CurrentLocationId = l.Id
left join residents d on d.DefaultLocationId = l.Id
where t.Id = @tenantId
请帮忙。 :祈祷:
您的问题包含 Locations
两次。不确定您 SQL 您要检索的内容。 CurrentLocationId
AND DefaultLocationId
匹配 LocationId
的居民?然后在 LINQ 语句中使用 AND。
如果是其他情况,那么 CurrentResidents 和 DefaultResidents 的类型是什么?相同 Resident
类型?那么你可能想要两套...
请提供更多信息...
正如 Felix 指出的那样,问题是您两次包含位置,这在 ef 核心中是不正确的。以下是实现此目标的方法:
var tenant = await context.Tenants
.IgnoreQueryFilters()
.Include(i => i.Locations.CurrentResidents.DefaultIfEmpty())
.Include(i => i.Locations.DefaultResidents.DefaultIfEmpty())
.FirstOrDefaultAsync(l => l.Id == tenantId, cancellationToken)
.ConfigureAwait(false);
调用一次 IgnoreQueryFilters 就足够了,你不需要调用它 3 次。
调用 where 和 first 或 default 是不必要的。您可以只使用第一个或默认的 lambda。
这就是我要找的东西:
var tenant = await context.Tenants
.IgnoreQueryFilters()
.Include(i => i.Locations).ThenInclude(x => x.CurrentResidents)
.Include(i => i.Locations).ThenInclude(x => x.CurrentResidents)
.FirstOrDefaultAsync(l => l.Id == tenantId)
.ConfigureAwait(false);
Sql 由 ef core 生成有点奇怪,但会产生我感兴趣的结果,所以一切都很好。
@bencel:感谢您指出这些问题。我专注于获取查询 运行,所以忽略了那些。
谢谢大家!!