You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF6中预加载关联数据获取指定TariffaOrariaLivello的优化方案

问题背景

我拥有如下实体模型类:

public class ClasseBase
{
    // 其他属性
    public EnumStato Stato { get; set; }
}

public class Gruppo : ClasseBase
{
    public int Id { get; set; }

    // 其他属性
    
    public virtual ICollection<Livello> Livelli { get; set; }
}

public class Livello : ClasseBase
{
    public int Id { get; set; }

    // 其他属性

    public byte Progressivo { get; set; }

    [ForeignKey(nameof(Gruppo))]
    public int IdGruppo { get; set; }
    public Gruppo Gruppo { get; set; }

    public virtual ICollection<TariffaOrariaLivello> TariffeOrarie { get; set; }
}

public class TariffaOrariaLivello
{
    public int Id { get; set; }

    [ForeignKey("Livello")]
    public int IdLivello { get; set; }
    public Livello Livello { get; set; }

    [DataType(DataType.Currency)]
    public decimal StraordinarioDiurno { get; set; }

    [DataType(DataType.Currency)]
    public decimal StraordinarioNotturno { get; set; }

    [DataType(DataType.Currency)]
    public decimal StraordinarioFestivoNotturno { get; set; }

    [DataType(DataType.Date)]
    public DateTime DataInizio { get; set; }

    [DataType(DataType.Date)]
    public DateTime? DataFine { get; set; }
}

对应的DbContext定义如下:

public DbSet<Livello> Livelli { get; set; }
public DbSet<Gruppo> Gruppi { get; set; }
public DbSet<TariffaOrariaLivello> TariffeOrarieLivello { get; set; }
需求说明

需要获取满足以下条件的TariffaOrariaLivello列表:

  • 关联的Livello.Stato为Attivo(激活状态);
  • 每个Livello仅保留DataInizio最新的一条记录;
  • 结果按Livello.Progressivo排序;
  • 每条TariffaOrariaLivello需预加载对应的Livello及其关联的Gruppo。
当前实现问题

我使用EF6开发,最初编写的代码未能成功加载关联数据,经尝试实现了借助匿名对象中转的可行方案,但该方案不够优雅。现寻求无需通过匿名对象列表的优化解决方案,感谢解答!

解决方案

可以通过两种方式实现无需匿名对象中转的查询,同时满足所有需求:

方式一:先获取最新记录ID集合(性能更优)

先筛选出每个激活状态Livello对应的最新TariffaOrariaLivello的ID,再基于ID查询主数据并预加载关联对象:

var latestTariffaIds = db.Livelli
    .Where(l => l.Stato == EnumStato.Attivo)
    .SelectMany(l => l.TariffeOrarie)
    .GroupBy(t => t.IdLivello)
    .Select(g => g.OrderByDescending(t => t.DataInizio).First().Id);

var result = db.TariffeOrarieLivello
    .Include(t => t.Livello)
    .Include(t => t.Livello.Gruppo)
    .Where(t => latestTariffaIds.Contains(t.Id))
    .OrderBy(t => t.Livello.Progressivo)
    .ToList();

方式二:单查询逻辑紧凑

通过子查询直接判断当前TariffaOrariaLivello是否为对应Livello的最新记录,同时完成筛选、预加载和排序:

var result = db.TariffeOrarieLivello
    .Include(t => t.Livello)
    .Include(t => t.Livello.Gruppo)
    .Where(t => t.Livello.Stato == EnumStato.Attivo
                && t.DataInizio == db.TariffeOrarieLivello
                    .Where(t2 => t2.IdLivello == t.IdLivello)
                    .Max(t2 => t2.DataInizio))
    .OrderBy(t => t.Livello.Progressivo)
    .ToList();

两种方案均无需依赖匿名对象中转,直接利用EF6的查询语法完成需求。方式一在数据量较大时性能表现更好,方式二则逻辑更简洁。

内容的提问来源于stack exchange,提问作者Liuc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 15:12:08