2013-12-18 48 views
3

我從數據庫中檢索數據(實體框架)使用的DTO:加載虛擬財產

IQueryable<User> users = repository.ListFiltered<User>(n => n.Active); 

var usersDTO = from user in users 
       select new UserAccountDTO{ 
        UserId = user.Id, 
        UserName = user.Name, 
        InstitutionName = user.Institution.Name, 
        InstitutionCountry = user.Institution.Country.Name 
       }; 

我這樣做是因爲用戶實體和機構實體,有很多的數據我現在不需要,所以我不想從數據庫中檢索它。

但問題是,我不喜歡的代碼,我想拆分代碼並連接選擇,有無論如何做到這一點?

我想到達這樣的:

users.LoadUserData().LoadInstitutionData(); 

你說什麼?可能嗎?

+0

所以'Institution'是導航屬性到'User'。你爲什麼不簡單地''選擇'在你的版本庫。ListFiltered ?然後最後做'.ToList()',因爲你試圖實現的是甚至是複雜的,而不是整潔的 –

+0

因爲我不想檢索所有的數據,我只需要一些字段,並且在某些條件下... –

回答

2

問題是什麼LoadUserData()LoadInstitutionData()應該看起來像。假設這個方法鏈的最終產品應該是IEnumerable<UserAccountDTO>。流利語法中的最後一個方法總是確定輸出。所以LoadInstitutionData()應該返回所需的IEnumerable。明確。

但是輸入呢?我看到兩個選擇:

  • 輸入是IEnumerable<User>(或IQueryable<User>)。好吧,那意味着LoadInstitutionData()不能做任何事情比你已經有的代碼。這不是一個解決方案,因爲你不喜歡代碼。此外,該方法需要user.InstitutionCountry必須加載或延遲加載,這是很難用任何形式的代碼合同表達。

  • 輸入是IEnumerable<UserAccountDTO>其中LoadUserData已經設置了直接user屬性和LoadInstitutionData應與Institution數據補充。現在的問題是:LoadInstitutionData應該怎麼做?無論如何,現在在一個查詢中完成的操作至少需要兩個查詢,甚至可以是1 + n。

更復雜的方案可能包括傳球和創作表達的,但肯定你會從煎鍋可以跳進火,重塑LINQ的擴展方法,或AutoMapper,或...

等待,AutoMapper。

您是否知道AutoMapper可以以一種可能吸引您的方式爲您做到這一點?

所有你需要的是一類

class UserAccountDTO 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    public string InstitutionName { get; set; } 
    public string InstitutionCountryName { get; set; } // Notice the Name part! 
}; 

映射

AutoMapper.Mapper.CreateMap<User, UserAccountDTO>(); 

一個使用:

using AutoMapper.QueryableExtensions; 

並有簡潔的語法:

var usersDTO = users.Project().To<UserAccountDTO>(); 

(當然還有來自NuGet的AutoMapper)。

Automapper將解決像InstitutionCountryNameuser.Institution.Country.Name屬性和投影的結果是一個表達式,它被翻譯成與聯接和所有一個SQL語句。這是我喜歡的代碼。

+0

啊,我不知道屬性名稱像「InstitutionCountryName」自動映射從Institution.Country.Name?很好的功能。 –

+0

謝謝!這很棒,但如果我必須使用集合,那又如何呢?那麼應用過濾器怎麼樣?可能嗎?我的意思是...如果我需要類似** public IEnumerable Institutions = user.Institutions.Where(n => n.Active)** –

+0

@ArielScherman AutoMapper也可以填充子集合。部分加載的集合是一個不同的章節。 EF不直接支持,但您可以更精細地實現它:http://stackoverflow.com/a/13904825/861716 –