简体   繁体   English

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

[英]Entity Framework Include Single Object from One-To-Many Relationship

I'm trying to construct a single query to fetch the list of all Tour objects, with each tour's latest version preloaded (latest being most recently created). 我正在尝试构建一个单一的查询来获取所有Tour对象的列表,每个tour的最新版本都是预先加载的(最近一次是最近创建的)。 See the models below. 请参阅以下型号。 Each Tour can have multiple associated TourVersion objects 每个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.
}

I'm able to accomplish what I want running another query for each Tour : 我能够完成我想要为每个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();
}

I'd like to be able to accomplish this in a single query. 我希望能够在一个查询中完成此任务。 Any suggestions? 有什么建议么?

Entity framework automatically loads related entities for you until the context is alive. 实体框架会自动为您加载相关实体,直到上下文处于活动状态。 You get the list of Tours by 你得到了Tours的列表

var tours = dbContext.Tours.ToList();

for example and you can get the tour version by calling 例如,你可以通过调用获得巡演版本

tours[i].CurrentTourVersion;

Unless dbContext is disposed somewhere before you get tour version in that case you are going to need eager loading (see here ). 除非在获得游览版本之前将dbContext放置在某个地方,否则您将需要急切加载(请参阅此处 )。 This way you get and keep the related objects. 这样您就可以获得并保留相关对象。

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

Ended up solving it with this: 结束解决它:

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();

Explanation of why this works: 解释为什么这有效:

  • Joins each tour with the most recent version 使用最新版本加入每个游览
    • Finds the most recent version by selecting version against maximum date 通过针对最大日期选择版本来查找最新版本
  • Creates an anonymous object with the TourId and CurrentTourVersion fields 使用TourId和CurrentTourVersion字段创建匿名对象
  • Maps that to a list of Tour objects 将其映射到Tour对象列表

EF has a restriction to force you to put the results of a join into an anonymous object. EF有一个限制,强制您将联接的结果放入匿名对象。 See this answer for more info 有关详细信息,请参阅此答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM