2017-07-04 44 views
2

我有這個類:c。與虛擬財產查詢#實體框架

public class Message 
    { 
     public Message() 
     { 
      Contacts = new List<Contact>(); 
     } 

     public Message(string Sub_Message, string Body_Message, string Date_Send_Message) 
     { 
      Contacts = new List<Contact>(); 

      Subject = Sub_Message; 
      Body = Body_Message; 
      Date = Date_Send_Message; 
     } 

     public int MessageId { get; set; } 
     public string Subject { get; set; } 

     public string Date { get; set; } 

     public string Body { get; set; } 

     public virtual IList<Contact> Contacts { get; set; } 
    } 

我想因爲這個消息是虛擬的,所有的延遲加載的東西來獲得聯繫的表,

這呼叫沒有工作對我得到這個錯誤:

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection. in Reference Table

語法:

public ObservableCollection<Model.Message> LoadMessages() 
    { 
     using (db) { 
     var x = from qr in db.Messages 
          order by qr.Subject 
          select qr; 
      } 
    } 

雖然這個工程:

public ObservableCollection<Model.Message> LoadMessages() 
{ 
    using (db) 
    { 
     var Messages = db.Messages.Include(z => z.Contacts).ToList(); 

     return new ObservableCollection<Model.Message>(Messages); 
    } 
} 

所以我使用的查詢一個叫MessageService服務中,每次我想使用的DbContext我爲它創建一個函數,並把它內部使用(DB)

像這樣:

 public class MessageService 
     { 
      ReadingFromData db = new ReadingFromData(); 
      public ObservableCollection<Model.Message> LoadMessages() 
      { 
       using (db) 
       { 
        //Do something with db 
       } 
      } 
} 

此外,有人可以給我解釋一下這是如何工作的,以及如何與實體框架查詢正確

工作

感謝

+0

請提供一些代碼,以顯示您如何使用上下文。如果連接關閉,延遲加載將不起作用。 – Harsh

+0

編輯帖子@Harsh – Zakk

回答

3

首先,你應該明白,這個代碼不查詢數據庫:

var x = from qr in db.Messages 
     orderby qr.Subject 
     select qr; 

它只是一個查詢定義(表達),它應該被翻譯成SQL和發送到數據庫服務器你會執行它。執行是枚舉查詢結果,或使用立即執行類型的LINQ運算符之一(請參閱Classification of Standard Query Operators by Manner of Execution)。即如果稍後在代碼中列舉了x,或者如果您嘗試將查詢結果存儲在列表中,則數據庫上下文db可能已被處置。當然,你會得到一個錯誤

var x = db.Messages; // query is not executed 
db.Dispose(); // context disposed 
foreach(var m in x) // exception here, you try to execute query which uses disposed context 
    ... 

現在關於延遲加載。它通過將數據庫上下文存儲在從您的實體繼承的代理實體中起作用。所以實際上db.Messages將返回某些類型的實體MessageWithDbContext與內部存儲的db值。這是需要額外的'懶'數據庫查詢以後。再次,如果在那個時間點處理數據庫上下文,那麼你會得到一個異常:

var x = db.Messages.ToList(); // query is executed, messages are loaded 
db.Dispose(); // context disposed 
foreach(var m in x) 
    m.Contacts.Count(); // exception - you try to execute contacts query with disposed db 

如何解決這個問題?請確保在處理查詢和進行其他「懶惰」調用時數據庫上下文不會丟失。或者在第二個例子中使用急切加載。預先加載可以讓你當你執行查詢的負載相關實體:

// both messages and contacts are loaded from database when you execute the query 
var x = db.Message.Include(m => m.Contacts).ToList(); 
db.Dispose(); 
foreach(var m in x) 
    m.Contacts.Count(); 

在這種情況下,不需要額外的「懶惰」的呼叫,這樣你就可以配置數據庫環境,並與查詢結果的工作。

+0

如此急切的加載立即獲得結果,而不是等到執行? – Zakk

+0

@Zakk急切的加載將會得到相關的實體,而不需要等到你需要它們。如果你不會執行它,查詢本身可以延期。用'ToList()'調用(參見第一個例子) –

1

只有在連接到上下文的連接打開(或未處理)時才訪問屬性,延遲加載纔有效。

  using (db) 
      { 
       //If you try to load the data here, lazy loading will work. 
      } 

現在,當您使用include時,EF會加載併爲您獲取相關數據。這就是爲什麼當你使用include時你的數據是可用的。

var Messages = db.Messages.Include(z => z.Contacts).ToList();