簡體   English   中英

實體框架 - 包括多個級別的屬性

[英]Entity Framework - Include Multiple Levels of Properties

Include() 方法非常適用於對象列表。 但是如果我需要 go 兩層深呢? 例如,下面的方法將返回具有此處顯示的包含屬性的 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; }
}

對於 EF 6

using System.Data.Entity;

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

確保using System.Data.Entity;添加using System.Data.Entity; 獲取Include lambda 的Include版本。


對於 EF 核心

使用新方法ThenInclude

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

如果我理解正確,您是在詢問包含嵌套屬性。 如果是這樣的話 :

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

或者

.Include("ApplicationsWithOverrideGroup.NestedProp")  

或者

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

EF Core:使用“ThenInclude”加載多個級別:例如:

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

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之后,它ThenInclude將您“重置”回頂級實體(講師)的級別。

您甚至可以多次重復相同的“第一級”集合 (CourseAssignments),然后是單獨的ThenIncludes命令以訪問不同的子實體。

請注意,您的實際查詢必須標記在IncludeThenIncludes鏈的末尾。 以下不起作用:

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

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

強烈建議您設置日志記錄並確保您的查詢不會失控,如果您包含的內容不止一兩件。 了解它的實際工作方式很重要 - 您會注意到每個單獨的“包含”通常是一個新查詢,以避免大量連接返回冗余數據。

如果您不打算實際編輯實體並重新保存, AsNoTracking可以大大加快速度。


EFCore 5 對將多組實體的查詢發送到服務器的方式進行了一些更改。 拆分查詢新的選項,可以通過更少的聯接使這種類型的某些查詢更有效,但請確保了解限制 - 並啟用日志記錄以避免以后出現性能意外。

我為 Entity Framework 6(.Net Core 風格)做了一個小助手,以一種很好的方式包含子實體。

它現在在 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();

該軟件包可在 GitHub 上獲得

我還必須使用多個包含,在第 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();

這可能對某人有所幫助:)

讓我明確指出,如果您不介意使用字符串文字,您可以使用字符串重載來包含嵌套級別,而不管對應關系的多重性如何:

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會為您照顧休息。 例子:

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

我有一個顯示 MbsNavigation.Name 的索引頁面,它是作為外鍵加載的固件 object。 固件 object 很大,因此通過 Inte.net 加載索引頁面需要幾分鍾時間。

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

這是僅加載 Firmware.Name 的解決方案:

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

現在索引立即加載。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM