Foreword:
我有两个项目.NET Core 3.1,一个EF Core 3.1.17,另一个在5.0.10上,在这两个版本中,我都使用了Include/thenClude,方式相同,一切都很好.
Problem:
当我试图在表达式中使用ThenClude语句时,当EF生成查询时,ThenClude中的所有实体都被忽略.
这是我的表达:
var settings = await _dbRepository.GetRegionRoles(systemId)
.Include(r => r.Region)
.Include(sr => sr.SystemRole)
.ThenInclude(ro => ro.Role)
.Include(gs => gs.GroupSettings)
.Where(w => w.GroupSettings.Any())
.ToListAsync(cancellationToken);
EF在生成查询之前识别所有ThenClude语句(我try 在可能的地方添加更多语句,得到了相同的结果),有跟踪日志(log):
Compiling query expression:
'DbSet<RegionRole>()
.Include(x => x.SystemRole)
.Where(w => w.SystemRole.SystemId.Equals((int)__systemId_0))
.Include(r => r.Region)
.Include(sr => sr.SystemRole)
.ThenInclude(ro => ro.Role)
.Include(gs => gs.GroupSettings)
.Include(sr => sr.SystemRole)
.ThenInclude(s => s.SystemCode)
.Where(w => w.GroupSettings
.Any())'
但生成的结果看起来像:
Generated query execution expression:
'queryContext => new SingleQueryingEnumerable<RegionRole>(
(RelationalQueryContext)queryContext,
RelationalCommandCache.SelectExpression(
Projection Mapping:
SELECT r.Id, r.CreatedByUser, r.CreatedDate //... and many other fields from each table
FROM Main.RegionRole AS r
INNER JOIN Main.SystemRole AS s ON r.SystemRoleId == s.Id
INNER JOIN Main.Region AS r0 ON r.RegionId == r0.Id
LEFT JOIN Main.GroupSettings AS g ON r.Id == g.RegionRoleId
WHERE (s.SystemId == CAST(@__systemId_0) AS int)) && EXISTS (
Projection Mapping:
SELECT 1
FROM Main.GroupSettings AS g0
WHERE (r.Id != NULL) && (r.Id == g0.RegionRoleId))
ORDER BY r.Id ASC, s.Id ASC, r0.Id ASC, g.Id ASC),
Func<QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator, RegionRole>,
K2Project.BE.DAL.Models.K2DbContext,
False,
False
)'
正如我们在这里看到的,thenClude语句中的实体"Role"在结果中缺失.
所有实体都具有导航属性,并在fluent api中进行了描述.所有表都有外键.
有一个实体"SystemRole"的示例
public class SystemRole
{
public Guid Id { get; set; }
public int RoleId { get; set; }
#region Dependencies
public virtual Role Role { get; set; }
#endregion
}
和fluent api:
public class SystemRoleEntityTypeConfiguration : IEntityTypeConfiguration<SystemRole>
{
public void Configure(EntityTypeBuilder<SystemRole> builder)
{
builder.ToTable(nameof(SystemRole), DbConst.MainSchemaName);
builder.HasKey(p => p.Id);
builder.Property(p => p.Id)
.ValueGeneratedOnAdd()
.HasDefaultValueSql("NEWSEQUENTIALID()");
builder.HasOne(p => p.Role)
.WithMany()
.HasForeignKey(f => f.RoleId)
.IsRequired(true);
}
}
Question:
在EF Core版本3.1.17和5.0.10中使用thenClude有什么区别?为什么相同的表达式适用于第一个版本,但不适用于另一个版本?也许我做错了什么,或者在更改框架版本时忘记了更改什么?
P、 在我的第二个项目中,从EF Core 5.0.10开始,所有包含Include/thenClude语句的表达式都做得很好.