我們使用實體框架4.2和模型優先方法以及DbContext代碼生成。實體框架中的異步查詢和延遲加載
比方說,我們有以下的實體框架數據模型:
class Person
{
public string Name { get; set; }
public Address Address { get; set; }
}
class Address
{
public string City; { get; set; }
}
的情況是以下幾點:
- 的ViewModel想從數據庫
- 任務(異步加載一些數據操作)是爲加載數據而創建的。這個 是因爲我們不希望UI在數據加載時凍結。
- 任務(它在一個單獨的線程執行)從數據庫中創建新 數據庫上下文和負荷數據(例如Person對象)
- 任務的完成和數據庫上下文被破壞。
- 主線程會收到關於任務完成的通知。主線程可以 現在訪問加載的Person對象。
- 視圖嘗試通過數據綁定
- 視圖以顯示人的姓名和地址在文本框中訪問Person.Name(這裏沒有問題)
- 的視圖訪問Person.Address.City - > OOPS!數據庫上下文已經被處置(因爲加載是在單獨的線程中完成的),並且由於惰性加載Person.Address不可訪問!
在第3階段,人被加載方式如下:
using (DatabaseContext context = new DatabaseContext())
{
Person person = from p in context.Persons.FirstOrDefault();
return person;
}
好吧,我知道(在理論上)我可能會迫使地址對象的裝載方式有兩種: 1)使用DbSet.Include,如:
context.Persons.Include("Address").FirstOrDefault();
2)訪問Person.Address而數據庫方面仍然活着,因爲這將迫使地址加載
Person person = context.Persons.FirstOrDefault();
Address address = person.Address;
return person;
當然第一個是優選的解決方案,因爲它不是那麼難看作爲第二個(只是訪問屬性以強制數據的裝載和丟棄然後結果是難看)。此外,如果是收集(例如人員列表),我將不得不循環收集並分別訪問每個人的地址。第一種解決方案的問題是隻有DbSet具有包含方法,而查詢返回的所有其他集合都沒有。所以,讓我們說我有以下的數據庫結構
class Resource {}
class Person : Resource { public Address Address { get; set; } }
class Appointment { public IList<Resource> Resources { get; set; } }
,我想加載所有的具體任命和包括在每一個資源,它是人的地址,我遇到了麻煩(或至少我想不出辦法來寫查詢它)。這是因爲context.Appointments.Resources不是DbSet類型的,而是沒有Include方法的ICollection。 (好吧,也許在這種情況下,我可以以context.Persons而不是上下文的方式編寫查詢。約會使我可以使用包括但也有許多場景中這是不可能的)
所以基本上,問題是:
- 這是一個正確的方式做異步訪問數據庫中第一個地方?
- 如何解決延遲加載問題?關閉延遲加載不是解決方案(除非它只能針對特定實體完成)