为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
Qyouu 2022-07-23 17:38:07
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();     }}
查看完整描述

3 回答

?
函数式编程

TA贡献1807条经验 获得超9个赞

我开始查看AutoMapper.Collection,这确实是我希望找到的扩展。实施后,我的列表会按照我的意愿进行更新。配置在我的使用中很简单,因为我只需要指定我的对象的 ID。


我的启动配置改为:


using AutoMapper;

using AutoMapper.EquivalencyExpression;

[....]

        public void ConfigureServices(IServiceCollection services)

        {

            services.AddAutoMapper(cfg => {

                cfg.AddCollectionMappers();

                });

        }

[....]

还有我的映射配置文件:


    CreateMap<SubItem, SubItemResource>().ReverseMap()

        .EqualityComparison((sir, si) => sir.Id == si.Id);


查看完整回答
反对 回复 2022-07-23
?
MM们

TA贡献1886条经验 获得超2个赞

这是一个比表面上看起来更难解决的问题。对您的列表进行自定义映射很容易,因为您了解您的应用程序;AutoMapper 没有。例如,是什么使源项等于目标项,以便 AutoMapper 能够辨别它应该映射现有的而不是添加的?PK?哪个属性是PK?该属性在源和目标上是否相同?这些是您可以在 .AutoMapper 中轻松回答的问题AfterMap,而不是 AutoMapper。

因此,AutoMapper 总是将集合映射为新项目。如果这不是你想要的行为,那就是这样的事情AfterMap。还要记住,AutoMapper 并不是专门为与 EF 一起使用而设计的,这才是真正的问题,而不是 AutoMapper。EF 的更改跟踪是导致 AutoMapper 的默认集合映射行为出现问题的原因。在其他情况和场景中,这不是问题。


查看完整回答
反对 回复 2022-07-23
?
翻阅古今

TA贡献1780条经验 获得超5个赞

我相信我已经实现了一个配置,其中我的 InputModels 和 EntityClasses 可以包含一个 Id,我只需要创建一个映射配置文件并调用:Mapper.Map(inputModelClassInstance, entityClassInstance);


因此 AutoMapper 和 EF CORE 将使用我的实例的 Id 来查看它们是否相等并按预期添加、删除或更新。


这是我所做的:


我用过:https ://github.com/AutoMapper/Automapper.Collection.EFCore


(链接中的修改代码):


var services = new ServiceCollection();

services

    .AddEntityFrameworkSqlServer() //Use your EF CORE provider here

    .AddDbContext<MyContext>(); //Use your context here


services.AddAutoMapper((serviceProvider, automapper) =>

{

    automapper.AddCollectionMappers();

    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 不会更新它们。


查看完整回答
反对 回复 2022-07-23
  • 3 回答
  • 0 关注
  • 220 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信