C# 加载虚拟属性
我正在使用DTO从数据库(使用实体框架)检索数据:C# 加载虚拟属性,c#,.net,entity-framework,projection,C#,.net,Entity Framework,Projection,我正在使用DTO从数据库(使用实体框架)检索数据: IQueryable<User> users = repository.ListFiltered<User>(n => n.Active); var usersDTO = from user in users select new UserAccountDTO{ UserId = user.Id, UserN
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
};
你怎么说?可能吗?问题是
LoadUserData()
和LoadInstitutionData()
应该是什么样子。假设此方法链的最终产品应该是IEnumerable
。fluent语法中的最后一个方法始终确定输出。因此LoadInstitutionData()
应该返回所需的IEnumerable
。清楚
但是输入呢?我看到两种选择:
- 输入为
(或IEnumerable
)。好的,这意味着IQueryable
除了您已有的代码之外,无法执行任何其他操作。这不是一个解决方案,因为你不喜欢代码。此外,该方法要求LoadInstitutionData()
和用户、机构
必须加载或可延迟加载,这很难在任何形式的代码契约中表达国家
- 输入为
,其中IEnumerable
设置了直接LoadUserData
属性,并且user
应使用LoadInstitutionData
数据进行补充。现在的问题是:Institution
应该如何做到这一点?无论如何,现在在一个查询中完成的操作将至少需要两个查询,甚至可能是1+nLoadInstitutionData
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>();
以及简洁的语法:
var usersDTO = users.Project().To<UserAccountDTO>();
var usersDTO=users.Project().To();
(当然还有NuGet的AutoMapper)
Automapper将像
InstitutionCountryName
这样的属性解析为user.Institution.Country.Name
,并且投影的结果是一个表达式,该表达式被转换为一个包含联接和all的SQL语句。这就是我喜欢的代码。所以机构
是用户
的导航属性。为什么不干脆。在存储库中选择。列表过滤?然后做.ToList()
,最后,因为你想要实现的是更复杂的,而不是更整洁的,因为我不想检索所有的数据,我只需要一些字段,在某些情况下…啊,我不知道像“InstitutionCountryName”这样的属性名称是从Institution.Country.name自动映射的?功能不错,谢谢!真是太棒了,但是如果我要处理收藏呢?那么应用过滤器呢?可能吗?我是说。。。如果我需要像public IEnumerable Institutions=user.Institutions.Where(n=>n.Active)这样的东西,@ArielScherman AutoMapper也可以填充子集合。部分加载的集合是另一章。EF不直接支持这一点,但您可以通过更详细的方式实现:
using AutoMapper.QueryableExtensions;
var usersDTO = users.Project().To<UserAccountDTO>();