[英]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)
...
...
;
我知道我可以單獨做,但我不想要,因為我有很多實體,我需要盡量減少數據庫請求。
我不想使用延遲加載,因為這也會產生許多數據庫請求。
如何做到這一點?
你可以嘗試這樣的事情:
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.