C# 实体框架 - 包括多级属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10822656/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 15:24:53  来源:igfitidea点击:

Entity Framework - Include Multiple Levels of Properties

c#entity-frameworkeager-loading

提问by Bob Horn

The Include() method works quite well for Lists on objects. But what if I need to go two levels deep? For example, the method below will return ApplicationServers with the included properties shown here. However, ApplicationsWithOverrideGroup is another container that holds other complex objects. Can I do an Include() on that property as well? Or how can I get that property to fully load?

Include() 方法非常适用于对象上的列表。但是如果我需要深入两层呢?例如,下面的方法将返回具有此处显示的包含属性的 ApplicationServers。但是,ApplicationsWithOverrideGroup 是另一个包含其他复杂对象的容器。我也可以在该属性上执行 Include() 吗?或者我怎样才能让该属性完全加载?

As it stands now, this method:

就目前而言,这种方法:

public IEnumerable<ApplicationServer> GetAll()
{
    return this.Database.ApplicationServers
        .Include(x => x.ApplicationsWithOverrideGroup)                
        .Include(x => x.ApplicationWithGroupToForceInstallList)
        .Include(x => x.CustomVariableGroups)                
        .ToList();
}

Will populate only the Enabled property (below) and not the Application or CustomVariableGroup properties (below). How do I make this happen?

将仅填充 Enabled 属性(下方),而不填充 Application 或 CustomVariableGroup 属性(下方)。我该如何做到这一点?

public class ApplicationWithOverrideVariableGroup : EntityBase
{
    public bool Enabled { get; set; }
    public Application Application { get; set; }
    public CustomVariableGroup CustomVariableGroup { get; set; }
}

采纳答案by Diego Torres

For EF 6

对于 EF 6

using System.Data.Entity;

query.Include(x => x.Collection.Select(y => y.Property))

Make sure to add using System.Data.Entity;to get the version of Includethat takes in a lambda.

确保添加using System.Data.Entity;以获取Includelambda 中的版本。



For EF Core

对于 EF 核心

Use the new method ThenInclude

使用新方法 ThenInclude

query.Include(x => x.Collection)
     .ThenInclude(x => x.Property);

回答by Judo

If I understand you correctly you are asking about including nested properties. If so :

如果我理解正确,您是在询问包含嵌套属性。如果是这样的话 :

.Include(x => x.ApplicationsWithOverrideGroup.NestedProp)

or

或者

.Include("ApplicationsWithOverrideGroup.NestedProp")  

or

或者

.Include($"{nameof(ApplicationsWithOverrideGroup)}.{nameof(NestedProp)}")  

回答by thangcao

EF Core:Using "ThenInclude" to load mutiple levels: For example:

EF Core:使用“ThenInclude”加载多个级别:例如:

var blogs = context.Blogs
    .Include(blog => blog.Posts)
        .ThenInclude(post => post.Author)
        .ThenInclude(author => author.Photo)
    .ToList();

回答by Lenny32

I made a little helper for Entity Framework 6 (.Net Core style), to include sub-entities in a nice way.

我为 Entity Framework 6(.Net Core 风格)做了一个小助手,以一种很好的方式包含子实体。

It is on NuGet now : Install-Package ThenInclude.EF6

它现在在 NuGet 上:Install-Package ThenInclude.EF6

using System.Data.Entity;

var thenInclude = context.One.Include(x => x.Twoes)
    .ThenInclude(x=> x.Threes)
    .ThenInclude(x=> x.Fours)
    .ThenInclude(x=> x.Fives)
    .ThenInclude(x => x.Sixes)
    .Include(x=> x.Other)
    .ToList();

The package is available on GitHub.

该软件包可在 GitHub 上获得

回答by dnxit

I also had to use multiple includes and at 3rd level I needed multiple properties

我还必须使用多个包含,在第 3 级我需要多个属性

(from e in context.JobCategorySet
                      where e.Id == id &&
                            e.AgencyId == agencyId
                      select e)
                      .Include(x => x.JobCategorySkillDetails)
                      .Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt.DurationType))
                      .Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt.RuleType))
                      .Include(x => x.Shifts.Select(r => r.Rate).Select(rt => rt.RateType))
                      .FirstOrDefaultAsync();

This may help someone :)

这可能对某人有所帮助:)

回答by Simon_Weaver

More EFCore examples on MSDNshow that you can do some quite complex things with Includeand ThenInclude.

MSDN 上的更多EFCore 示例表明您可以使用Include和做一些非常复杂的事情ThenInclude

This is a good example of how complex you can get (this is all one statement!):

这是一个很好的例子,说明你可以得到多么复杂(这只是一个声明!):

viewModel.Instructors = await _context.Instructors

      .Include(i => i.OfficeAssignment)

      .Include(i => i.CourseAssignments)
        .ThenInclude(i => i.Course)
            .ThenInclude(i => i.Enrollments)
                .ThenInclude(i => i.Student)

      .Include(i => i.CourseAssignments)
        .ThenInclude(i => i.Course)
            .ThenInclude(i => i.Department)

      .AsNoTracking()
      .OrderBy(i => i.LastName)
      .ToListAsync();

See how you can chain Includeeven after ThenIncludeand it kind of 'resets' you back to the level of the top level entity (Instructors).

看看你如何Include甚至在之后链接ThenInclude,它有点“重置”你回到顶级实体(讲师)的级别。

You can even repeat the same 'first level' collection (CourseAssignments) multiple times followed by separate ThenIncludescommands to get to different child entities.

您甚至可以多次重复相同的“第一级”集合 (CourseAssignments),然后是不同的ThenIncludes命令以访问不同的子实体。

Note your actual query must be tagged onto the end of the Includeor ThenIncludeschain. The following does NOT work:

请注意,您的实际查询必须标记在IncludeorThenIncludes链的末尾。以下不起作用:

var query = _context.Instructors.AsQueryable();
query.Include(i => i.OfficeAssignment);

var first10Instructors = query.Take(10).ToArray();

Would strongly recommend you set up logging and make sure your queries aren't out of control if you're including more than one or two things. It's important to see how it actually works - and you'll notice each separate 'include' is typically a new query to avoid massive joins returning redundant data.

强烈建议您设置日志记录并确保您的查询不会失控,如果您包含的内容不止一两件。了解它的实际工作方式很重要 - 您会注意到每个单独的“包含”通常是一个新查询,以避免大量连接返回冗余数据。

AsNoTrackingcan greatly speed things up if you're not intending on actually editing the entities and resaving.

AsNoTracking如果您不打算实际编辑实体并重新保存,则可以大大加快速度。

回答by mrmashal

Let me state it clearly that you can use the string overload to include nested levels regardless of the multiplicities of the corresponding relationships, if you don't mind using string literals:

让我明确指出,如果您不介意使用字符串文字,您可以使用字符串重载来包含嵌套级别,而不管对应关系的多重性如何:

query.Include("Collection.Property")