使用 AutoMapper 添加、更新和删除 List 中的项目

AutoMapper 是否没有本地方法来更新需要删除、添加或更新实例的嵌套列表?


我在带有 EF Core 的 ASP.Net Core 应用程序中使用 AutoMapper 将我的 API 资源映射到我的模型。这对我的大多数应用程序来说都运行良好,但我对更新映射嵌套列表的解决方案不满意,其中列出的实例需要保留。我不想覆盖现有列表,我想删除传入资源中不再存在的实例、添加新实例并更新现有实例。


型号:


public class MainObject

{

    public int Id { get; set; }

    public List<SubItem> SubItems { get; set; }

    

}


public class SubItem

{

    public int Id { get; set; }

    public int MainObjectId { get; set; }

    public MainObject MainObject { get; set; }

    public double Value { get; set; }

}

资源:


public class MainObjectResource

{

    public int Id { get; set; }

    public ICollection<SubItemResource> SubItems { get; set; }

    

}


public class SubItemResource

{

    public int Id { get; set; }

    public double Value { get; set; }

}

控制器:


public class MainController : Controller

{

    private readonly IMapper mapper;

    private readonly IMainRepository mainRepository;

    private readonly IUnitOfWork unitOfWork;


    public MainController(IMapper mapper, IMainRepository mainRepository, IUnitOfWork unitOfWork)

    {

        this.mapper = mapper;

        this.mainRepository = mainRepository;

        this.unitOfWork = unitOfWork;

    }


    [HttpPut("{id}")]

    public async Task<IActionResult> UpdateMain(int id, [FromBody] MainObjectResource mainObjectResource)

    {

        MainObject mainObject = await mainRepository.GetMain(id);

        mapper.Map<MainObjectResource, MainObject>(mainObjectResource, mainObjectResource);

        await unitOfWork.CompleteAsync();


        return Ok(); 

    }

}


Qyouu
浏览 224回答 3
3回答

函数式编程

我开始查看AutoMapper.Collection,这确实是我希望找到的扩展。实施后,我的列表会按照我的意愿进行更新。配置在我的使用中很简单,因为我只需要指定我的对象的 ID。我的启动配置改为:using AutoMapper;using AutoMapper.EquivalencyExpression;[....]&nbsp; &nbsp; &nbsp; &nbsp; public void ConfigureServices(IServiceCollection services)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; services.AddAutoMapper(cfg => {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; cfg.AddCollectionMappers();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; }[....]还有我的映射配置文件:&nbsp; &nbsp; CreateMap<SubItem, SubItemResource>().ReverseMap()&nbsp; &nbsp; &nbsp; &nbsp; .EqualityComparison((sir, si) => sir.Id == si.Id);

MM们

这是一个比表面上看起来更难解决的问题。对您的列表进行自定义映射很容易,因为您了解您的应用程序;AutoMapper 没有。例如,是什么使源项等于目标项,以便 AutoMapper 能够辨别它应该映射现有的而不是添加的?PK?哪个属性是PK?该属性在源和目标上是否相同?这些是您可以在 .AutoMapper 中轻松回答的问题AfterMap,而不是 AutoMapper。因此,AutoMapper 总是将集合映射为新项目。如果这不是你想要的行为,那就是这样的事情AfterMap。还要记住,AutoMapper 并不是专门为与 EF 一起使用而设计的,这才是真正的问题,而不是 AutoMapper。EF 的更改跟踪是导致 AutoMapper 的默认集合映射行为出现问题的原因。在其他情况和场景中,这不是问题。

翻阅古今

我相信我已经实现了一个配置,其中我的 InputModels 和 EntityClasses 可以包含一个 Id,我只需要创建一个映射配置文件并调用:Mapper.Map(inputModelClassInstance, entityClassInstance);因此 AutoMapper 和 EF CORE 将使用我的实例的 Id 来查看它们是否相等并按预期添加、删除或更新。这是我所做的:我用过:https ://github.com/AutoMapper/Automapper.Collection.EFCore(链接中的修改代码):var services = new ServiceCollection();services&nbsp; &nbsp; .AddEntityFrameworkSqlServer() //Use your EF CORE provider here&nbsp; &nbsp; .AddDbContext<MyContext>(); //Use your context hereservices.AddAutoMapper((serviceProvider, automapper) =>{&nbsp; &nbsp; automapper.AddCollectionMappers();&nbsp; &nbsp; automapper.UseEntityFrameworkCoreModel<MyContext>(serviceProvider);}, typeof(DB).Assembly);var serviceProvider = services.BuildServiceProvider();然后我CreateMap<>()的看起来像这样:CreateMap<InputModelClass, EntityClass>(MemberList.Source);CreateMap<ChildInputModelClass, ChildClass>(MemberList.Source);我只需通过以下方式执行更新://Fetch entityClassInstance from db:var entityClassInstance = Context.EntityClasses.Where(ec => ex.id == id).Include(ec => ec.children).FirstOrDefault();//Perform update:Mapper.Map(inputModelClassInstance, entityClassInstance);我可以在父子集合中添加和删除,EF CORE + AutoMapper 将按预期添加、删除和更新。我相信.UseEntityFrameworkCoreModel<MyContext>(serviceProvider)添加了 AutoMapper 将使用 Ids 来比较要添加、删除和更新的配置。重要提示:包含子实体非常重要,否则 AutoMapper 不会更新它们。
打开App,查看更多内容
随时随地看视频慕课网APP