使用AutoMapper查找相关对象并将其添加为属性

本文关键字:添加 属性 对象 AutoMapper 查找 使用 | 更新日期: 2023-09-27 18:14:27

我有一个运行在Entity Framework 6, Model First上的应用程序,运行在一个遗留数据库上。

在应用程序中,我们有一个Person对象,它有一个或多个Address对象。它们使用一个额外的标签链接:PersonXAddress,如下所示:

Person
    Id
    Name
    ...

PersonXAddress
    PersonId
    AddressId
Address
   Id
   Street
   PostalCode
   ...

使用AutoMapper,我已经添加了一个属性到我的PersonDto"HomeAddres",这是AddressType == 1的地址,像这样:

Mapper.CreateMap<Person, PersonDto>()
   .ForMember(x => x.HomeAddress,
       o => o.MapFrom(y => y.PersonXAddresses
              .Where(a => a.Address.AddressTypeId == 1)
              .Select(x => x.Address).FirstOrDefault();

所以在我的代码中,我永远不需要遍历所有不同的地址来找到那个人的HomeAddress。

但是,我发现这是非常缓慢的。它创建了一个巨大的sql查询(大约50行sql),第一次运行这个查询可能需要30秒。在第一次触发它之后,查询从数据库中获取一些Person对象可能需要大约1秒钟的时间。我发现,如果我注释掉上面的映射,生成的查询将在不到一秒的时间内启动,并在几毫秒内返回结果。

是否有更好的方法自动查找家庭住址?你能在我需要改进的地方给我一些帮助吗?

Thanks to lot

使用AutoMapper查找相关对象并将其添加为属性

你看起来有一个建模问题。在Person模型(和数据库表)上应该有一个HomeAddress。你在LINQ查询中假设有零个或一个家庭地址。只需在数据库级别显式地建模。

试试用LINQ:

var personDTO = context.Person
               .Where(p => p.Id == 1)
               .Select(p => new {
                  person = p,
                  homeAddress = p.PersonXAddresses
                                 .FirstOrDefault(px => px.Address.AddressTypeID == 1)
                                 .Address })
               .Select(pd > new PersonDto {
                   Id = person.Id
                   Name = person.Name,
                   ...
                   HomeAddress = homeAddress
               }).ToList();

同时,确保你有适当的索引(AddressTypeID等)。

现在可以使用AutoMapper Queryable extensions库中的AutoMapper ProjectTo<>扩展来解决这个问题。

您的查询现在可以看起来像这样(使用EF Plus IncludeFilter扩展为方便,并假设您的EF模式已经抽象掉了交叉引用表):

context.Persons
       .IncludeFilter(p => p.Addresses.Where(a => a.AddressTypeId == 1))
       .ProjectTo<PersonDTO>();

你的地图应该是这样的:

Mapper.CreateMap<Person, PersonDTO>()
      .ForMember(x => x.HomeAddress,
                 o => o.MapFrom(y => y.Addresses.FirstOrDefault()));

使用ProjectTo<>扩展的优点是,对数据库本身的查询将只包括映射所需的字段,从而避免了过度订阅问题。与往常一样,请确保为表连接建立索引,以提高性能。