2015-10-05 74 views
2

我有一個查詢,它連接兩個在Entity Framework中沒有已定義關係的表,並且已連接的表具有一個到一個第三個表的一對多導航屬性。Eager正在加載加入

msg與作業之間存在一對多關係,但沒有外鍵,並且在.EDMX中沒有定義關聯。

作業和鎖定之間存在一對多關係,並且在.EDMX中定義了一個關聯,因此作業有一個job.locks導航屬性並且鎖具有lock.job導航屬性。

我原來的查詢:

var msgsAndJobs = (
    from m in dbContext.msgs 
    join j in dbContext.jobs 
     on new { jobid = m.jobid, priority = m.priority } 
     equals new { jobid = j.jobid, priority = j.priority } 
    where m.msgtype == "EMERGENCY" 
    orderby new { m.recvdt } 
    select new { m, j } 
    ); 

我發現,EF是生成一個查詢的加入,則執行第二查詢來填充每個導航性能和聯接返回的每一條記錄。

微軟的文檔說明問題:https://msdn.microsoft.com/en-us/data/jj574232.aspx

所以我認爲我能夠使用.INCLUDE()子句,急切地加載所涉及的記錄。但它似乎並不奏效:

我的新查詢:

var msgsAndJobs = (
    from m in dbContext.msgs 
    join j in dbContext.jobs.Include("locks") 
     on new { jobid = m.jobid, priority = m.priority } 
     equals new { jobid = j.jobid, priority = j.priority } 
    where m.msgtype == "EMERGENCY" 
    orderby new { m.recvdt } 
    select new { m, j } 
    ); 

,它仍然產生每個職位鎖定的查詢。

任何想法我做錯了什麼?

+0

'使用System.Data.Entity;'將添加支持lambda表達式重載'包括' –

+0

得到了lambda表達式的工作,但查詢仍然是懶加載... –

+0

你試過只是做一個投影鎖沒有包含甚至更好...手動添加您的連接到鎖? – ewahner

回答

2

這就是Include的問題。這太容易使它失效,並不總是清楚它爲什麼不起作用。打破Include的一件事是changing the shape of the query。另一個是projecting to a non-entity type or an anonymous type

這似乎令人難以置信很難預測何時Include什麼,不工作,但有一個簡單的一招:Include如果您在查詢結束應用它始終工作。

如果你不能在那裏應用它,它不會有效。

考慮到這一點,如果我們看看你的情況,很清楚爲什麼Include不起作用。你不能這樣做

(... select new { m, j }).Include("locks"); // Runtime error 

因爲locks不是匿名的形式的導航性能,效果顯着。

(... select new { m, j }).Include(x => x.locks); // Doesn't compile 

所以你Include是無效的,並且locks按需加載:如果您使用的λ版本它更明顯。

幸運的是,由於關係修正有一條出路,即EF通過其導航屬性將上下文中的實體編織在一起的過程。更改您的查詢到這一點:

var msgsAndJobs = (
    from m in dbContext.msgs 
    join j in dbContext.jobs 
     on new { jobid = m.jobid, priority = m.priority } 
     equals new { jobid = j.jobid, priority = j.priority } 
    where m.msgtype == "EMERGENCY" 
    orderby new { m.recvdt } 
    select new { m, j, j.locks } 
    ).AsEnumerable() 
    .Select(x => new { x.m, x.j }); 

如果你執行這個查詢,.AsEnumerable()導致結果被加載到環境中,之後就可以選擇你本來想的結果。現在您會注意到EF已經填充了所有job.locks集合。

儘管一件重要的事情是:您必須禁用延遲加載,否則尋址job.locks集合仍將觸發延遲加載。這是因爲即使集合已填充,它在內部也不標記爲Loaded

+0

這似乎工作,謝謝。 –

+0

這對EF6不起作用。 –

+0

@GertArnold - 我遵循上面描述的模式,導航屬性沒有填充。因此,它不適合我。 –

相關問題