C# 加载虚拟属性

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

我正在使用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
               };

你怎么说?可能吗?

问题是
LoadUserData()
LoadInstitutionData()
应该是什么样子。假设此方法链的最终产品应该是
IEnumerable
。fluent语法中的最后一个方法始终确定输出。因此
LoadInstitutionData()
应该返回所需的
IEnumerable
。清楚

但是输入呢?我看到两种选择:

  • 输入为
    IEnumerable
    (或
    IQueryable
    )。好的,这意味着
    LoadInstitutionData()
    除了您已有的代码之外,无法执行任何其他操作。这不是一个解决方案,因为你不喜欢代码。此外,该方法要求
    用户、机构
    国家
    必须加载或可延迟加载,这很难在任何形式的代码契约中表达

  • 输入为
    IEnumerable
    ,其中
    LoadUserData
    设置了直接
    user
    属性,并且
    LoadInstitutionData
    应使用
    Institution
    数据进行补充。现在的问题是:
    LoadInstitutionData
    应该如何做到这一点?无论如何,现在在一个查询中完成的操作将至少需要两个查询,甚至可能是1+n

更复杂的替代方案可能包括传递和组合表达式,但您肯定会从煎锅跳进火中,重新发明LINQ的扩展方法,或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>();
以及简洁的语法:

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>();