2012-11-06 32 views
1

爲什麼我的模型相關的屬性再出門到DB已經被在一個單獨的LINQ連接語句加載冗餘DB訪問?LINQ的相關車型

背景信息:

我最近跑了一些性能配置上我的ASP.NET MVC3 LINQ的應用我有,我希望能解決一些莫名其妙的結果。

這裏是分貝結構的簡化版本。外鍵關係已建立。

表客戶:

ID|Client Name|Vertical ID| 
___________________________ 
1 |Client1 |2   | 
2 |Client2 |5   | 
3 |Client3 |   | 

表垂直

ID|Vertical Name| 
_________________ 
2 |Life   | 
5 |Guilt  | 

當我顯示客戶的名單,我展示他們的客戶名稱和垂直。我的控制器很簡單:

public ActionResult Index() 
    { 
     ... 
    var model = repository.GetAllClients(); 
     return View(model); 
    } 

獲取所有客戶端在垂直表(以及其他幾個)上運行連接。

public IEnumerable<client> GetAllClients() 
    { 
     OperationsMetricsDataContext db = new OperationsMetricsDataContext(); 
     var clients = from c in db.clients 
         join v in db.verticals on c.vertical equals v into tmp1 
         from v in tmp1.DefaultIfEmpty() 
         join sm in db.cel_sm_staffs on c.sm_id equals sm.cel_sm_id into tmp2 
         from sm in tmp2.DefaultIfEmpty() 
         join cel in db.cel_sm_staffs on c.cel_id equals cel.cel_sm_id into tmp3 
         from cel in tmp3.DefaultIfEmpty() 
         select c; 
     return clients; 
    } 

在我看來,我則嘗試顯示垂直名字我已經在我的部分客戶端類使用這種方法勢必

public string getVerticalName() 
    { 
     return this.vertical == null ? "N/A" : this.vertical.vertical_name; 
    } 

問題:

@foreach (var item in Model) { 
<tr> 
    <td> 
     @Html.Raw(item.client_name) 
    </td> 
    <td> 
     @Html.Raw(item.getVerticalName()) 
    </td> 

的我發現的問題是,即使我在原始模型中指定了連接(並且我已經能夠驗證垂直屬性具有值在模型被傳遞到視圖之前加載),每次我調用getVerticalName方法時,Linq會自動再次出去到數據庫加載垂直,以便我可以訪問垂直名稱。這是非常低效的,因爲我最終爲每個客戶端單獨調用db調用以獲取垂直信息。

我在這裏錯過了什麼? LINQ不應該知道該屬性已經綁定,並且不會去數據庫檢索它,或者有什麼我需要指定告訴LINQ我的信息已經存在於模型中?

回答

2

不知道如何表現在MVC,但也許你的問題是延遲加載相關的實體。 您可以使用LoadOptions強制Linq-2-sql急切加載。

嘗試

OperationsMetricsDataContext db = new OperationsMetricsDataContext(); 

DataLoadOptions dlo = new DataLoadOptions(); 
dlo.LoadWith<Client>(c => c.Vertical); 
db.LoadOptions = dlo; 
+0

謝謝。延遲加載是問題。 – Rondel

0

我的第一印象是,得到的查詢只執行一次,你應該改變:return clients;return clients.ToList();

由於你的代碼,我相信這是返回一個IQueryable簡單地鑄造爲IEnumerable,並通過設計IQueryable的意志隨時訪問服務器枚舉。

+0

使用'ToList'枚舉和早期綁定我曾試圖但這並沒有解決問題。使用LINQ eager loading是關鍵。雖然 – Rondel

+0

是的,但我並不知道DataLoadOptions的設置和用法,所以很高興知道它可以在哪裏使用 – Thymine