如何通过LINQ查询构建嵌套视图模型

时间:2017-07-30 20:00:24

标签: c# entity-framework linq

下面的查询返回4行,所有行都对应一个adres信息,因此有一个“adresType”列代表其HomeAddress,WorkAdress等。 这是AllAddressViewModel:

public class AllAddressViewModel
    {
        public AddressModel homeAddress{ get; set; }
        public AddressModel workAddress { get; set; }
    }

    public class AddressModel
    {
        public adresTypeEnum adresType{ get; set; }
        ...

这就是我正在尝试的;

var result = (       from Muayene in muayeneRepo
                          join Adres in adresRepo on Muayene.HastaTc equals Adres.HastaTc
                          where Muayene.HastaTc == hastaTc.ToString() && Muayene.IsDeleted != true
                          select new HastaMuayeneKayitViewModel()
                          {
                              homeAddress= new AddressModel {
                                  adresType= Adres.AddressType,
                                  ...
                              },
                              workAddress = new AddressModel 
                              {
                                  adresType= Adres.AdresTipi,
                                  ...

我想你已经明白了什么困扰我,我应该将所有adresType与相应的视图模型匹配。我如何在linq中正确填充模型,不想要另一步。

1 个答案:

答案 0 :(得分:1)

对于Muayene / w 4地址的连接将导致同一父记录的4条记录,每条记录都有一个地址。

如果地址记录具有区别字段(地址类型),那么第一步可能是将继承引入您的域模型,以便Muayene包含一组地址,但该集合将包含0-1(或更多)每个适用的地址类型作为从Address继承的不同实体类型。这样,您可以更轻松地将这些转换为相应的视图模型。 (参见每层次结构继承表。https://msdn.microsoft.com/en-us/data/jj618292

为了构建视图模型结构,您需要通过Muayene进行分组,以便为​​每个父项及其子地址集合或更好地获取组,使用导航属性来处理此问题。

很难从您的代码示例中判断出来,但是如果muayeneRepo和addressRepo是基于数据库表返回IEnumerable等的存储库,那么这将是性能的潜在问题。通常你会从DBSets中获取这些信息。您还应该利用域中的导航属性,以便Muayene实体具有ICollection的地址。

使用基于上下文的示例:

var muayenes = _context.Muayenes.Include(x => x.Addresses)
.Where(x => x.HastAc == hastAc && false == x.IsDeleted)
.ToList(); // Materializes these entities so further operations are Linq2Object

如果您没有导航属性并希望加入DbSets,那么您可以通过加入实体然后执行GroupBy来完成相同的操作,其中组密钥是父实体,分组值是地址。

我通常使用的下一步是添加构造函数或工厂类来处理从我的实体填充视图模型的新实例,或者连接类似AutoMapper的东西来执行此操作。通常情况下,我只是自己连接它,因为它通常比在其他地方查找映射规则时更容易理解,试图弄清楚为什么会发生变化。

例如:

:(构造函数)

var viewModels = muayenes.Select(x => new HastaMuayeneKayitViewModel(x)).ToList();

或(工厂)

var viewModels = muayens.Select(x => HastaMuayeneKayitViewModelFactory.Create(x)).ToList();

可以使用相同的原则构建地址。

填充视图模型和子视图模型的逻辑可以移到支持代码并重新使用,而不是以大型Linq表达式结束。