簡體   English   中英

EF Lambda 包含導航屬性

[英]EF Lambda include navigation properties

我有以下對象,名為 Filter ,具有以下屬性:

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

    public virtual ICollection<Type> Types{ get; set; }
    public virtual ICollection<Step> Steps { get; set; }
    public virtual ICollection<Flow> Flows { get; set; }
    public virtual ICollection<Room> Rooms { get; set; }

當我從數據庫中選擇過濾器列表時,我不知道如何包含集合(類型、步驟、流程、房間)。 我的代碼如下:

var filters = (
            from filter in dbContext.DbSet<Filter>()
            let rooms = (
                from r in dbContext.DbSet<Room>()
                select r
                )
            let eventTypes = (
                from t in dbContext.DbSet<Type>()
                select t
                )
            let processFlows = (
                from f in dbContext.DbSet<Flow>()
                select f
                )
            let processFlowSteps = (
                from s in dbContext.DbSet<Step>()
                select s
                )
            select filter
            ).ToList();

我的Filter集合返回了,但是里面的集合是空的。 你能告訴我我怎樣才能做到這一點?

Ps:由於性能問題,我不想使用 Include,我不喜歡 Entity Framework 生成查詢的方式,我想這樣做。

您需要使用Include擴展方法:

var filters=dbContext.DbSet<Filter>()
                     .Include(f=>f.Types)
                     .Include(f=>f.Steps)
                     .Include(f=>f.Flows)
                     .Include(f=>f.Rooms)
                     .ToList()

更新

@MrSilent, Include擴展方法正是為了加載相關實體而制作的,我認為您擁有的另一個選項是執行原始 sql ,但是您正在做的方式並不是您對數據庫進行四次往返的方法,並且您需要改用 join 來獲取相關實體, Include為您生成這些連接,而這只是一次往返。

這是,例如,我猜你可以這樣做的另一種方式,但同樣,它違背了使用 EF 的目的,你的模型的想法也是表示表之間的關系,而不僅僅是單獨表示它們

var query= from f in context.DbSet<Filter>()
           from s in f.Steps
           from r in f.Rooms
           from t in f.Types
           from fl in f.Flows
           select new {f, s, r, t, fl};

你的方法有效,你只是做錯了。

要包含導航屬性,您所要做的就是一個子選擇(使用 linq),例如:

var filters = (from filter in dbContext.DbSet<Filter>()
                select new Filter
                {
                    filter.Id,
                    filter.Name,
                    Rooms = (from r in dbContext.DbSet<Room>()
                            where r.FilterId == filter.Id
                            select r).ToList()
                }).ToList();

請記住,在您調用返回方法(ToList、Any、FirstOrDefault 等)之前,EF 不會執行查詢。 有了這個,而不是通過不使用 Include() 來執行那些你想避免的丑陋查詢,它只會觸發兩個查詢並正確分配你想要的對象中的值。

您可以使用延遲加載,方法如下:

您首先需要獲得 Include 傾向於虛擬的屬性,然后是受保護訪問類型的空構造函數才能很好地完成您的工作。

public virtual ICollection<Type> Types{ get; set; }
public virtual ICollection<Step> Steps { get; set; }
public virtual ICollection<Flow> Flows { get; set; }
public virtual ICollection<Room> Rooms { get; set; }

 //FOR EF !
 protected Filter() { }

我認為此解決方案將解決您的問題。

暫無
暫無

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

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