2014-02-06 78 views
4

我發現了很多其他帖子,但他們面對完全相同的問題。他們使用的代碼略有不同。所以我認爲值得回顧一下。實體框架6上下文不檢索導航屬性

我先使用EF6代碼,然後創建了一個具有一些導航屬性的客戶端實體。

我會發布相關的代碼,考慮還有一些屬性和外鍵,但與問題無關。模型正在生成。

public class Client 
{ 
    public Client() 
    { 
     JobsExperiences = new Collection<JobsExperience>(); 
     CapacitationCourses = new Collection<CapacitationCourse>(); 
     ScholarLevelDetails = new Collection<ScholarLevelDetail>(); 
     Relatives = new Collection<Relative>(); 
    } 
    public long ClientID { get; set; } 
    public virtual ICollection<ScholarLevelDetail> ScholarLevelDetails { get; set; } 

    public virtual ICollection<JobsExperience> JobsExperiences { get; set; } 
} 

現在,我創建了一個ClientServices類,我把那獲取或往返於數據庫發送數據。所有的方法,療法我有這樣的代碼,這是工作隨機,I'll儘量解釋清楚。

internal Client GetClient(string userId, bool lazyLoadingEnabled = true) 
    { 
     using (var context = new ApplicationDbContext()) 
     { 
      context.Configuration.LazyLoadingEnabled=lazyLoadingEnabled; 

      var client = (from _client in context.Client 
          where _client.ApplicationUserId == userId 
          select _client).FirstOrDefault(); 

      return client; 
     } 
    } 

我的目標有些情況下是隻獲得了客戶的屬性,有時所有的屬性,包括導航屬性。

在我的控制器我有這樣

var client = uuc.GetClient(user.Id, false); 

線或這

var client = uuc.GetClient(user.Id); 

當我運行的第一句話,導航屬性初始化但都有數= 0,即使我的數據庫有關聯的記錄。我認爲,如果延遲加載被禁用,則意味着啓用加載,但似乎不是。但是,導航屬性中沒有Load()方法來強制加載。

當運行第二句,在導航屬性拋出異常「client.ScholarLevelDetails」扔類型「System.ObjectDisposedException」的異常。這句話在句子後面引出一行,引起手錶中的導航屬性。但是,這是最奇怪的部分,如果我退回到句子並調試進入方法,所有導航屬性都會正確加載。

爲什麼代碼的行爲不同,如果一次運行而不是跑步進入方法? 我認爲使用語句範圍在導航屬性加載之前完成,但爲什麼禁用lay loading doe snot檢索它們呢? 我該如何編碼以獲得一致的行爲?

回答

4

我用這個改變了Linq中的查詢代碼Ihad。

internal Client GetClient(string userId, bool lazyLoadingEnabled = true) 
    { 
     using (var context = new ApplicationDbContext()) 
     { 
      context.Configuration.LazyLoadingEnabled = lazyLoadingEnabled; 

      var client = context 
         .Client 
         .Include(s => s.ScholarLevelDetails) 
         .Include(s => s.JobsExperiences) 
         .Include(s => s.CapacitationCourses) 
         .Include(s => s.Relatives) 
         .FirstOrDefault(s => s.ApplicationUserId == userId); 

      return client; 
     } 
    } 

而現在它的工作。不過,我仍然有一些問題需要與您的讀者和同事討論。

爲什麼平原Linq不工作? 爲什麼懶惰加載是否啓用並不重要,這段代碼每次都是一樣的?

+0

您的線路'context.Configuration.LazyLoadingEnabled = lazyLoadingEnabled;'沒有爲您做任何事情。您渴望加載所有的導航屬性,這就是它工作的原因。簡單的LINQ確實有效,但是沒有看到你嘗試過的例子,我們無法告訴你爲什麼你的實現不起作用。 –

+0

除了我在問題中發佈的內容,還需要了解我們是否可以解開Linq沒有工作的原因?同時發佈我可以發佈的所有東西 –

+0

看起來,如果您想使用查詢語法,您需要選擇一種匿名類型,其中包含所需的所有數據。 http://stackoverflow.com/questions/6761104/how-does-linq-expression-syntax-work-with-include-for-eager-loading –

3

問題是,在導航屬性可以加載之前,上下文超出了範圍。你需要改變你如何使用你的上下文,或者只是通過表join(s)使用你正在使用的查詢語法來加載你需要的實體,或者通過.Include() lambda表達式,如果您使用lambda查詢語法。

using (var context = new ApplicationDbContext()) 
    { 
     context.Configuration.LazyLoadingEnabled=lazyLoadingEnabled; 

     var client = (from _client in context.Client 
         where _client.ApplicationUserId == userId 
         select _client).FirstOrDefault(); 

     return client; //at this point, your context is gone, and no 
     //navigational properties will be loaded onto your client object, 
     //even if you try to navigate them. You may even get exceptions if 
     //attempting to navigate to some properties. 
    } 

下面是一個加入例如:

var client = (from _client in context.Client 
       join t in context.Table on _client.Val equals t.val //this will eager load Table property on client. 
       where _client.ApplicationUserId == userId 
       select _client).FirstOrDefault(); 
+0

我嘗試了其中一個導航屬性,在延遲加載中都有true和false,但不起作用。 啓用lazyloading時,導航屬性不會在上下文生命週期內加載;當禁用時,屬性被初始化但是爲空。 –

2

您應該使用包括特性的方法。

_context.Client.Include(c=>c.JobsExperiences) ... and all props like this 

但是對你來說最好不要使用延遲加載。 從方法返回後,原因上下文變爲非活動狀態。

+0

只需在使用中的懶惰loaidng行後添加一個,每個nav屬性一個,但它不起作用。我試着懶加載啓用和禁用。在這兩種情況下,nav屬性都被初始化,但是是空的。 –

1

使用EF 6,我不得不使用(蘭巴的和客戶端的關鍵字是不可用):

using (var context = new SyntheticData.EF.DBContext()) 
    { 
     var item = (from t in context.TEMPLATEs 
         .Include("DATASET") 
         .Include("COLUMNs") 
         .Include("SORTs") 
         .Include("FILTERs") 
        where t.USERID == identityname && t.ID == id select t).FirstOrDefault(); 
     return item; 
    } 

這填補了關係類與語法,如:

  • item.DATASET.xxx
  • item.COLUMNs [0] .xxx

「使用(var context)」構造是很好的做法,因爲它起作用es連接到數據庫將被釋放回池中。如果你不這樣做,你可能會因爲忙碌的系統而失去聯繫。

0

以防萬一這有助於某人我沒有得到任何導航屬性,我的問題似乎是EF沒有正確地連接屬性,因爲我使用的接口作爲導航屬性類型,我需要使用實際類型。除非有人知道如何使用註釋或某些東西來告知EF屬性映射到的實際類型。