2013-12-18 49 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 –