【问题标题】:How to map a derived class to a base class property with Automapper如何使用 Automapper 将派生类映射到基类属性
【发布时间】:2017-01-30 21:38:19
【问题描述】:

首先,如果我的上述问题令人困惑,我既不熟悉 Automapper 的使用,也不太了解术语,而且很少问这样的问题,所以我可能会尝试将我的想法表达为一个听起来很荒谬的问题。

我创建了一些从基类继承的类,因为我打算将基类重用于比下面显示的实体更多的实体。为简单起见,我将保留类的属性无效。

我的问题是 PersonBusiness 属性的映射。当我使用 EF 6 从 SQL 加载数据时,我看到它将 PersonBusiness 对象的 Person 和 Business 属性加载为 Employee 对象和 Branch 对象,因为这是我为查询而拉回的,但是当我尝试映射Employee 对象和 Branch 对象从 PersonBusiness 对象到 PersonBusinessD 对象,它将它们加载为 Person 和 Business 类类型;显然忽略了派生类中包含的所有属性。

很明显,鉴于加载到 PersonBusiness 对象中的数据,Person 和 Business 属性是对象引用变量,可以使用派生类型 Employee 和 Branch 加载,但由于某种原因,Automapper 看到 Employee 和 Branch 对象并且只映射它们到 Person 和 Business 的基本类型。

这是从数据库加载数据的示例:

这是映射到 PersonBusinessDto 的数据示例:

以下是我用来将实体映射到 DTO 的基本类结构和映射,它们适用于除 PersonBusiness 映射之外的所有内容。

Entity.cs

public abstract class Entity : IEntity
{

}

EntityDto.cs

public abstract class EntityDto : IEntityDto
{

}

Person.cs

public abstract class Person : Entity
{
    public List<PersonBusiness> PersonBusinesses { get; set; };
}

PersonDto.cs

public abstract class PersonDto : EntityDto
{
    public List<PersonBusinessDto> PersonBusinesses { get; set; };
}

Employee.cs

public class Employee : Person
{

}

EmployeeDto.cs

public class EmployeeDto : PersonDto
{

}

Business.cs

public abstract class Business : Entity
{
    public List<PersonBusiness> PersonBusinesses { get; set; };
}

BusinessDto.cs

public abstract class BusinessDto : EntityDto
{
    public List<PersonBusinessDto> PersonBusinesses { get; set; };
}

分支.cs

public class Branch : Business
{

}

BranchDto.cs

public class BranchDto : BusinessDto
{

}

PersonBusiness.cs

public class PersonBusiness
{
    public int PersonId { get; set; }
    public int BusinessId { get; set; }
    public Enums.RoleType RoleType { get; set; }

    public Person Person { get; set; }
    public Business Business { get; set; }
}

PersonBusinessDto.cs

public class PersonBusinessDto
{
    public int PersonId { get; set; }
    public int BusinessId { get; set; }
    public Enums.RoleType RoleType { get; set; }

    public PersonDto Person { get; set; }
    public BusinessDto Business { get; set; }
}

AutoMapperConfig.cs

public class ProfileMapping
        : Profile
    {
        private readonly IMapperConfiguration _mappingConfiguration;

        public ProfileMapping(IMapperConfiguration config)
        {
            _mappingConfiguration = config;
        }

        protected override void Configure()
        {
            _mappingConfiguration.AllowNullDestinationValues = true;

            _mappingConfiguration
                .CreateMap<Person, PersonDto>()
                .ForMember(dto => dto.PersonBusinesses, opt => opt.MapFrom(src => src.PresonBusinesses));

            _mappingConfiguration
                .CreateMap<Employee, EmployeeDto>()

            _mappingConfiguration
                .CreateMap<Business, BusinessDto>()
                .ForMember(dto => dto.PersonBusinesses, opt => opt.MapFrom(src => src.PresonBusinesses));

            _mappingConfiguration
                .CreateMap<Branch, BranchDto>();

            _mappingConfiguration
                .CreateMap<PersonBusiness, PersonBusinessDto>()
                .ForMember(dto => dto.Business, opt => opt.MapFrom(src => src.Business))
                .ForMember(dto => dto.Person, opt => opt.MapFrom(src => src.Person));
        }
    }

【问题讨论】:

    标签: c# entity-framework-6 automapper


    【解决方案1】:

    这里发生的情况是EmployeeBranch 分别被向上转换为PersonBusiness,因为它们是PersonBusiness 类中的实际类型。然后,当 AutoMapper 进行映射时,它会看到 PersonBusiness 类型,因此根据配置将它们映射到 PersonDtoBusinessDto

    对象仍然是EmployeeBranch 的实例,即使它们被向上转换;你可以转回EmployeeBranch。但是,AutoMapper 正在创建 PersonDtoBusinessDto 的实际实例,因此您不能将它们转换为 EmployeDtoBranchDto

    没有一个具有实际正确属性类型的类,您必须在映射期间将它们转换回正确的类型,这将是一个真正的痛苦。原则上,您将遇到MapFrom 无法返回不同派生类型的问题,因为 lambda 只能返回一种类型。

    AutoMapper 提供了一些guidance 来说明如何使这种事情发挥作用。但是,您会注意到它直接处理实例,而不是这些实例的属性。我不确定实际上如何做你需要做的事情,除了在从PersonBusiness 映射到PersonBusinessDto 时简单地忽略映射这些属性,然后使用 AutoMapper 文档详细信息的方法显式映射属性,即

    personBusinessDto.Person = Mapper.Map(personBusiness.Person, personBusiness.Person.GetType(), typeof(PersonDto));
    

    就像我说的:真正的痛苦。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-03
      • 1970-01-01
      • 2021-04-30
      • 2021-02-27
      • 1970-01-01
      • 2015-10-27
      • 1970-01-01
      相关资源
      最近更新 更多