C# 如何将多个LINQ Include()语句分配给变量以供代码重用?
我想在变量中存储一组C# 如何将多个LINQ Include()语句分配给变量以供代码重用?,c#,linq,asp.net-core,entity-framework-core,C#,Linq,Asp.net Core,Entity Framework Core,我想在变量中存储一组.include()语句,因为我需要在多个位置使用相同的includes。因此,为了防止代码重复,我提出以下问题: 例如,以下面的查询为例,我将在其中加载多个相关实体: var record = await db.DisplacementDamageRecords .Include(tr => tr.Mission) .ThenInclude(m => m.MissionRadiationPartsLead)
.include()
语句,因为我需要在多个位置使用相同的includes
。因此,为了防止代码重复,我提出以下问题:
例如,以下面的查询为例,我将在其中加载多个相关实体:
var record = await db.DisplacementDamageRecords
.Include(tr => tr.Mission)
.ThenInclude(m => m.MissionRadiationPartsLead)
.Include(tr => tr.Mission)
.ThenInclude(m => m.MissionInstruments)
.ThenInclude(mi => mi.Instrument)
.Include(tr => tr.Mission)
.ThenInclude(m => m.MissionInstruments)
.ThenInclude(mi => mi.CognitiveEngineer)
.Include(tr => tr.ProcurementPart)
.ThenInclude(pp => pp.Part)
.FirstOrDefaultAsync(tr => tr.Id == form.Id);
提取包含的内容将非常有用,如下所示:
var testRecordIncludes =
.Include(tr => tr.Mission)
.ThenInclude(m => m.MissionRadiationPartsLead)
.Include(tr => tr.Mission)
.ThenInclude(m => m.MissionInstruments)
.ThenInclude(mi => mi.Instrument)
.Include(tr => tr.Mission)
.ThenInclude(m => m.MissionInstruments)
.ThenInclude(mi => mi.CognitiveEngineer)
.Include(tr => tr.ProcurementPart)
.ThenInclude(pp => pp.Part)
这样我就可以像这样使用这个变量:
var record = await db.DisplacementDamageRecords
.testRecordIncludes()
.FirstOrDefaultAsync(tr => tr.Id == form.Id);
这可能吗?谢谢 您可以定义如下扩展方法:
public static class DbExtensions
{
public static IQueryable<DisplacementDamageRecord> TestRecordIncludes(this IQueryable<DisplacementDamageRecord> records)
{
return records
.Include(tr => tr.Mission)
.ThenInclude(m => m.MissionRadiationPartsLead)
.Include(tr => tr.Mission)
.ThenInclude(m => m.MissionInstruments)
.ThenInclude(mi => mi.Instrument)
.Include(tr => tr.Mission)
.ThenInclude(m => m.MissionInstruments)
.ThenInclude(mi => mi.CognitiveEngineer)
.Include(tr => tr.ProcurementPart)
.ThenInclude(pp => pp.Part);
}
}
我建议创建一个更通用的扩展方法,并根据需要在子类上调用它,或者在基类上保留子类默认应具有的导航属性作为nav属性数组
此扩展方法有两个参数,一个是要包含在查询中的导航属性列表,另一个是includealrecords
public virtual IQueryable<TEntity> GetAll(string[] includeNavProp = null, bool includeAllRecords = false)
{
IQueryable<TEntity> query = includeAllRecords ? TableNoTracking.IgnoreQueryFilters() : Table;
if (includeNavProp != null)
{
query = includeNavProp.Aggregate(query, (current, includePath) => current.Include(includePath));
}
return query;
}
也就是说,您可以用这种方式调用GetAll
var ddr = db.DisplacementDamageRecords.GetAll(new []{
"Mission.MissionRadiationPartsLead",
"Mission.MissionInstruments.Instrument",
"Mission.MissionInstruments.CognitiveEngineer",
"Mission.ProcurementPart.Part")
现在取决于您如何对导航属性进行分组,以使其可重用
希望这对您有所帮助您知道是否可以允许使用不同的类型吗?例如,我也将在dynamictrorecord
类型上使用此选项。您在这里看到的include都是从TestRecord
基类继承的。因此,如果我们将您的扩展名更改为typeTestRecord
correct,这应该会起作用。我不确定我是否理解这个问题。您可以定义多个扩展方法,您可以为每个可重用场景定义一个扩展方法。因此,在您的示例中,我们定义了一种类型的IQueryable
。此类型(DisplacementDamagerRecord)继承自TestRecord
的基类。您看到的所有包含的都是我的TestRecord
类的成员。我还有另一个名为dynamictrorecord
的TestRecord
子类,我想对其使用此扩展方法。因此,理论上,如果我们将扩展方法定义为IQueryable
,那么它应该适用于我的子类,仍然正确吗?我可以很快进行测试,只是想确认一下,我用一个解决方案更新了您提到的问题的答案。我必须将通用代码添加到TestRecordIncludes中,但除此之外,这是我需要的。谢谢!一旦更新,我将标记为正确
public virtual IQueryable<TEntity> GetAll(string[] includeNavProp = null, bool includeAllRecords = false)
{
IQueryable<TEntity> query = includeAllRecords ? TableNoTracking.IgnoreQueryFilters() : Table;
if (includeNavProp != null)
{
query = includeNavProp.Aggregate(query, (current, includePath) => current.Include(includePath));
}
return query;
}
public abstract class BaseEntityTypeConfiguration<T> : IEntityTypeConfiguration<T> where T : BaseEntity
{
public virtual void Configure(EntityTypeBuilder<T> builder)
{
builder.HasKey(p => p.Id);
builder.Property(dt => dt.Id).UseSqlServerIdentityColumn();
builder.Property(x => x.CreatedBy).HasMaxLength(50).IsRequired();
builder.Property(x => x.CreatedOn).IsRequired();
builder.Property(x => x.UpdatedBy).HasMaxLength(50).IsRequired();
builder.Property(x => x.UpdatedOn).IsRequired();
builder.HasQueryFilter(app => !app.IsDeleted);
}
}
var ddr = db.DisplacementDamageRecords.GetAll(new []{
"Mission.MissionRadiationPartsLead",
"Mission.MissionInstruments.Instrument",
"Mission.MissionInstruments.CognitiveEngineer",
"Mission.ProcurementPart.Part")