簡體   English   中英

按實體類型的 EF 條件包含

[英]EF Conditional Include by Entity Type

請假設該架構:

public class Mammal
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Dog : Mammal
{
    public int TailId { get; set; }
    public Tail Tail { get; set; }
}

public class Bat : Mammal
{
    public int WingId { get; set; }
    public Wing Wing { get; set; }
}

public class Buffalo : Mammal
{
    public virtual ICollection<Horn> Horns { get; set; }
}

public class Tail
{
    public int Id { get; set; }
    ...
}

public class Wing
{
    public int Id { get; set; }
    ...
}

public class Horn
{
    public int Id { get; set; }
    ...
}

現在,我的上下文:

public class MyContext : DbContext
{
    public DbSet<Mammal> Mammals { get; set; }
}

因此,我只想進行一個 sql 查詢,並包含(並加載)所有嵌套實體,例如:

var query = myContext.Mammals
    .IncludeIfTypeIs<Dog>(d => d.Tail)
    .IncludeIfTypeIs<Bat>(b => b.Wing)
    .IncludeIfTypeIs<Buffalo>(b => b.Horns)
    ...
    ...
;

我知道我可以單獨做,但我不想要,因為我有很多實體,我需要盡量減少數據庫請求。

我不想使用延遲加載,因為這也會產生許多數據庫請求。

如何做到這一點?

EF Core 在 2.1 及更高版本中支持此功能。 此處查看 Github 問題

var query = myContext.Mammals
    .Include(d => (d as Dog).Tail)
    .Include(b => (b as Bat).Wing)
    .Include(b => (b as Buffalo).Horns)

這將包括一個查詢中的所有屬性。

這是官方文檔的鏈接。

你可以嘗試這樣的事情:

public static class Extensions
{
    public static IQueryable<Mammal> IncludeExtraEntities<Mammal,T>(this IQueryable<Mammal> query, T derivedType) where T :Mammal
    {
        if (derivedType is Dog)
            return query.Include("Tail");
        if (derivedType is Bat)
            return query.Include("Wing");
        return query;
    }
}

然后在你的數據庫調用中:

var query = myContext.Mammals.IncludeExtraEntities(typeof(Dog));

也許這會奏效。

您可以創建一個方法來包含表達式列表。 (或者可能是一種擴展方法)。

public static IQueryable<Mammal> GetMammals(params Expression<Func<T, Object>>[] includeExps)
{
     var query = context.Mammals.AsQueryable();
     if (includeExps != null)
        query = includeExps.Aggregate(query, (current, exp) => current.Include(exp));

     return query;

}

然后,在您的代碼中:

//Bat and Dog will be included here
var mammals = GetMammals(i => i.Bat, i => i.Dog);

希望能幫助到你!

問題是,如何加載派生類型的屬性,只使用基類的 DbSet 而沒有延遲加載? 恐怕這是不可能的。

但是,您可以這樣做:

public class MyContext : DbContext
{
    public DbSet<Mammal> Mammals { get; set; }
    public DbSet<Dog>    Dogs    { get; set; }
    public DbSet<Bat>    Bats    { get; set; }
}

您也可以簡單地實現一種方法,針對您的每種類型

public static class Extensions
{
    public static IQueryable<Dog> IncludeExtraEntities<Dog>(this IQueryable<Dog> query) where Dog : Mammal
    {
            return query.Include("Tail");
    }

    public static IQueryable<Bat> IncludeExtraEntities<Bat>(this IQueryable<Bat> query) where Bat: Mammal
    {
            return query.Include("Wing");
    }
}

然后,您可以簡單地調用:

myContext.Dogs.IncludeExtraEntities();

並且將調用取決於您的類型的方法。

您對Include期望過高。 您在Include輸入的 lambda 表達式只是一個看起來過於智能的字符串提供程序。 在幕后,它的成員表達式被剖析以獲取屬性的名稱,僅此而已。 該名稱被輸入到接受字符串參數的Include方法中。 該方法執行實際工作。

lambda 表達式必須指向IQueryable類型的導航屬性。 你不能做...

myContext.Mammals.Include(d => d.Tail)

...因為Tail不是基本類型的屬性。 你只能做...

myContext.Mammals.OfType<Dog>().Include(d => d.Tail)

你能得到的最好的東西是

from m in context.Mammals
let tail = (m as Dog).Tail
let wing = (m as Bat).Wing
let horns= (m as Buffalo).Horns
select new { Mammal = m, tail, wing, horns }

由於所有內容都已轉換為 SQL,因此您不必擔心空引用異常。

我遇到了這樣的問題,在這里我是如何解決它的:

 public IEnumerable<OrderLine> GetAllOrderLinesData()
    {
        var _StockOrderLines = appContext.OrderLines.OfType<StockOrderLine>()
            .Include(p => p.Order).Include(p => p.Product);

        var _AnnualOrderLines = appContext.OrderLines.OfType<AnnualOrderLine>()
            .Include(p => p.Order).Include(p => p.Customer);

        return _StockOrderLines.ToList<OrderLine>().Union<OrderLine>(_AnnualOrderLines.ToList<OrderLine>());
    }

你可以改變你的課程:)

暫無
暫無

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

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