2012-10-22 11 views
2

將Func保存爲變量並將其傳遞給實體框架選擇與在select內部鍵入內聯轉換相反,它與之之間有什麼區別?使用對象初始化程序內聯的細微差別與將一個變量傳遞給EF選擇

Func<Models.Contact,ViewModels.Contact> ToViewModel = 
    c => new ViewModels.Contact() 
    { 
     ID = c.ID, 
     ... 
     UserName = c.User.UserName 
    }; 

... 

return dc.Contacts.Select(ToViewModel); 

,而不是

return dc.Contacts.Select(c => new ViewModels.Contact() 
{ 
    ID = c.ID, 
    ... 
    UserName = c.User.UserName 
}); 

我問這個,因爲雖然這兩種方法的工作,也得空和一些其他的東西微妙的不同反應,我不明白爲什麼。

例如,在這種情況下,聯繫人可能有也可能沒有用戶,所以用戶可能會也可能不會爲空。當內聯輸入初始化程序時,它將使該屬性優雅地失效爲空。但是,當通過變量傳遞相同的初始值時,它將拋出一個NullReferenceException。

這是爲什麼?

請注意,我想保存初始化程序的原因是,它可以在每個CRUD操作中重用,以便從WebApi返回對象。如果需要在響應中添加或刪除一段時間的屬性,那麼必須複製和粘貼該類的選擇會很麻煩。

回答

4

第二個示例編譯爲Expression<Func<Contact, Contact>>,EF在服務器上運行。 (使用IQueryable接口)
它轉換爲使用OUTER JOIN的SQL查詢,該OUTER JOIN不會生成空引用異常。

您的第一個示例不是表達式樹,因此它將通過接口IEnumerable<T>並在客戶端上執行。
通過將ToViewModel更改爲Expression<Func<...>>,可以使其行爲與第一個示例相同。

相關問題