拆分过长的IIncludableQueryable<>

时间:2017-02-27 16:11:32

标签: entity-framework asp.net-core

我有一个相当复杂的数据模型,有30多个表。我正在使用Web API向Angular 2前端提供数据,并发现下载一个"整个"最容易。考虑到这并不涉及很多数据,所以它的所有子类都在一个项目中。

然而,我现在正在看下面的怪物:

var query = context.GlobalBcf
    .Include(x => x.Location)
    .Include(x => x.RadioEquipment.Model)
    .Include(x => x.RadioEquipment.RadioEquipmentSuppliers).ThenInclude(x => x.Supplier)
    .Include(x => x.RadioEquipment.RadioEquipmentTypes).ThenInclude(x => x.Type)
    .Include(x => x.GlobalBcfPowerSupplies).ThenInclude(x => x.PowerSupply)
    .Include(x => x.GlobalBcfApplications).ThenInclude(x => x.Application)
    .Include(x => x.OvtpType)
    .Include(x => x.BatteryType)
    .Include(x => x.AmountBattery)
    .Include(x => x.Bcfs)
    .Include(x => x.Bcfs).ThenInclude(x => x.Mode)
    .Include(x => x.Bcfs).ThenInclude(x => x.TrxSigBw1)
    .Include(x => x.Bcfs).ThenInclude(x => x.TrxSigBw2)
    .Include(x => x.Bcfs).ThenInclude(x => x.TrxSigBw3)
    .Include(x => x.Bcfs).ThenInclude(x => x.TrxSigBw4)
    .Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment).ThenInclude(x => x.Btses)
    .Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.ExternalComponent)
    .Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.Type)
    .Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.FrequenceRepeaters).ThenInclude(x => x.Model)
    .Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.FrequenceRepeaters).ThenInclude(x => x.Supplier)
    .Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.MasterUnits).ThenInclude(x => x.Model)
    .Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.MasterUnits).ThenInclude(x => x.PowerSupply)
    .Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.MasterUnits).ThenInclude(x => x.Supplier)
    .Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.MasterUnits).ThenInclude(x => x.OpticRepeaters).ThenInclude(x => x.OtrxModel)
    .Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.MasterUnits).ThenInclude(x => x.OpticRepeaters).ThenInclude(x => x.RuModel)
    .Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.MasterUnits).ThenInclude(x => x.OpticRepeaters).ThenInclude(x => x.RuPowerSupply)
    .Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.MasterUnits).ThenInclude(x => x.OpticRepeaters).ThenInclude(x => x.RuMode)
    .AsQueryable();

return query.Single(x => x.Id == message.Id);

这显然很难维护,所以我想知道是否有可能将其拆分成更小,更易于维护的部分,而不是一遍又一遍地重复这些部分:

  • .Include(x => x.Bcfs)
  • .Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments)
  • .Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters)
  • .Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.MasterUnits)
  • .Include(x => x.Bcfs).ThenInclude(x => x.BcfSegments).ThenInclude(x => x.Segment.Repeaters).ThenInclude(x => x.MasterUnits).ThenInclude(x => x.OpticRepeaters)

任何提示,指示,想法?

1 个答案:

答案 0 :(得分:0)

我找到了一个解决方案,只需将代码片段分成不同的扩展名:

class SupraBigZone {
    public List<Zone> Zones {get; set;}
}

class Zone {
    public SupraBigZone SupraBigZone {get; set;}
    public List<SmallZone> SmallZones {get; set;}
}

class SmallZone {
    public Zone Zone {get; set;}
}

然后你有一个包含SupraBigZone的课程:

class Game {
    public SupraBigZone GameZone {get; set;}

    public OtherProperty OtherProperty {get; set;}
}

public static class IQueryableExtensions
{
    public static IIncludableQueryable<T, Zone> IncludeSupraBigZone<T>(this IQueryable<T> values, Func<T,SupraBigZone> getSupraBigZone) where T : class
    {
        return values
            .Include(c => getSupraBigZone(c)).ThenInclude(h => h.Zones).ThenInclude(z => z.SupraBigZone)
            .Include(c => getSupraBigZone(c)).ThenInclude(h => h.Zones).ThenInclude(z => z.SmallZones).ThenInclude(s => s.Zone);
    }
}

请注意,扩展名将Zone作为第二个泛型类型,这是因为在此示例中,最后一个包含区域。

在您的DbContext中,您可以按如下方式使用它:

public DbSet<Game> Games { get; set; }

public IQueryable<Car> GameWithDependencies
{
    get
    {
        return
            Games
            .IncludeSupraBigZone(g => g.GameZone)
            .Include(g => g.OtherProperty);
    }
}