实体框架-包括多层属性

Include()方法适用于对象上的list。但如果我需要深入两层呢?例如,下面的方法将返回包含如下所示属性的ApplicationServers。然而,ApplicationsWithOverrideGroup是另一个包含其他复杂对象的容器。我可以在这个属性上做一个Include()吗?或者如何让该属性完全加载?

按照目前的情况,这种方法:

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

将只填充Enabled属性(下面),而不填充Application或CustomVariableGroup属性(下面)。我该怎么做呢?

public class ApplicationWithOverrideVariableGroup : EntityBase
{
public bool Enabled { get; set; }
public Application Application { get; set; }
public CustomVariableGroup CustomVariableGroup { get; set; }
}
337716 次浏览

如果我理解正确,您正在询问包括嵌套属性。如果有:

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

.Include("ApplicationsWithOverrideGroup.NestedProp")

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

EF 6

using System.Data.Entity;


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

确保添加using System.Data.Entity;以获得接受lambda的Include版本。


EF Core

使用新方法ThenInclude

using Microsoft.EntityFrameworkCore;


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

英孚的核心:使用"ThenInclude"加载多个级别: 例如:< / p >

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

我做了一个小的帮助实体框架6(。Net Core样式),以一种很好的方式包含子实体。

它是在NuGet现在:安装包然后包括。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();

这个包是可以在GitHub上找到

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

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

这可能会帮助到某些人:)

MSDN上的EFCore示例表明你可以用IncludeThenInclude做一些相当复杂的事情。

这是一个很好的例子,你可以得到多么复杂的(这都是一个链式语句!):

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

你可以有多个Include调用——即使在ThenInclude之后,它也会将你“重置”回顶级实体(instructor)的级别。

你甚至可以多次重复相同的“一级”集合(CourseAssignments),然后使用单独的ThenIncludes命令来获得不同的子实体。

注意,您的实际查询必须标记在IncludeThenIncludes链的末尾。以下不工作:

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


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

强烈建议你设置日志记录,并确保你的查询不失控,如果你包括一个或两个以上的东西。了解它的实际工作原理非常重要——你会注意到每个单独的“include”通常都是一个新查询,以避免大量连接返回冗余数据。

AsNoTracking可以大大加快事情,如果你不打算实际编辑实体和保存。


EFCore 5对多组实体的查询发送到服务器的方式进行了一些更改。有拆分查询的新选项可以使这种类型的某些查询更有效,使用更少的连接,但请确保了解限制-并启用日志记录,以避免以后的性能意外。

让我清楚地说明一下,你可以使用字符串重载来包含嵌套的级别,而不管对应关系的多样性,如果你不介意使用字符串字面量:

query.Include("Collection.Property")

我要把我的解加到我的特定问题上。我需要包括两个相同级别的系列。最终的解是这样的。

var recipe = _bartendoContext.Recipes
.Include(r => r.Ingredients)
.ThenInclude(r => r.Ingredient)
.Include(r => r.Ingredients)
.ThenInclude(r => r.MeasurementQuantity)
.FirstOrDefault(r => r.Id == recipeId);
if (recipe?.Ingredients == null) return 0m;
var abv = recipe.Ingredients.Sum(ingredient => ingredient.Ingredient.AlcoholByVolume * ingredient.MeasurementQuantity.Quantity);
return abv;

这是计算给定饮料配方中酒精含量的百分比。正如你所看到的,我只是把食材集合包括了两次,然后把食材和数量包括在上面。

我想出了一个最简单的方法。你不需要安装软件包ThenInclude。EF或者你不需要对所有嵌套的导航属性使用ThenInclude。只要按照下面的步骤去做,EF会为您照顾好休息。 例子:< / p >
var thenInclude = context.One.Include(x => x.Twoes.Threes.Fours.Fives.Sixes)
.Include(x=> x.Other)
.ToList();

我有一个索引页面,显示MbsNavigation。作为外键加载的固件对象的名称。固件对象很大,因此通过Internet加载索引页需要几分钟。

BatterySystem = await _context.BatterySystems.Include(b => b.MbsNavigation)

这是一个加载固件的解决方案。名字只有:

BatterySystem = await _context.BatterySystems
.Include(b => b.MbsNavigation)
.Select(b => new BatterySystem()
{
Name = b.Name,
MbsNavigation = new Firmware() { Name = b.MbsNavigation.Name },
})
.ToListAsync();

现在索引立即加载。