实体框架包括一对多关系中的单个对象

本文关键字:单个 对象 关系 框架 包括 一对多 实体 | 更新日期: 2023-09-27 18:16:07

我试图构建一个查询来获取所有Tour对象的列表,每个Tour的最新版本都是预加载的(最新的是最近创建的)。请看下面的模型。每个Tour可以有多个相关联的TourVersion对象

class Tour {
    public Guid TourId { get; set; }
    public virtual TourVersion CurrentTourVersion { get; set; }
    // Other properties etc.
}
class TourVersion {
    public Guid TourId { get; set; }
    public DateTime CreatedOn { get; set; }
    // Other properties etc.
}

我能够完成我想要为每个Tour运行另一个查询:

var tours = context.Tours.ToList();
foreach (var tour in tours)
{
    tour.CurrentTourVersion = context.TourVersions
        .Where(t => t.TourId == tour.Id)
        // ToUnixTime is a custom extension method that returns a long
        .OrderByDescending(t => t.CreatedOn.ToUnixTime())
        .FirstOrDefault();
}

我希望能够在单个查询中完成此操作。有什么建议吗?

实体框架包括一对多关系中的单个对象

实体框架会自动为你加载相关的实体,直到上下文处于活动状态。您可以通过

获得旅游列表
var tours = dbContext.Tours.ToList();
例如

,您可以通过调用

来获取tour版本。
tours[i].CurrentTourVersion;

除非dbContext在你得到tour版本之前就被处理掉了,在这种情况下你将需要急切加载(见这里)。通过这种方式,您可以获得并保留相关对象。

var tours = dbContext.Tours.Include(obj=>obj.CurrentTourVersion).ToList();

最终解决了这个问题:

var tours = (from tour in context.Tours
             join v in context.TourVersions on tour.TourId equals v.TourId
             where v.CreatedOn == context.TourVersions.Select(b => b.CreatedOn).Max()
                select new
                {
                    TourId = tour.Id,
                    CurrentTourVersion = v
                }).ToList().Select(tour => new Tour
                {
                    TourId = tour.Id,
                    CurrentTourVersion = tour.CurrentTourVersion
                });
return tours.ToList();

工作原理解释:

  • 使用最新版本加入每个巡演
    • 通过根据最大日期选择版本来查找最新版本
  • 创建一个带有TourId和CurrentTourVersion字段的匿名对象
  • 将其映射到Tour对象列表

EF有一个限制,强制您将连接的结果放入匿名对象中。