Sup*_*pez 5 c# automapper entity-framework-core asp.net-core
AutoMapper 是否没有本地方法来更新需要删除、添加或更新实例的嵌套列表?
你好,我在我的 ASP.Net Core 应用程序中使用 AutoMapper 和 EF Core 将我的 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; }
}
Run Code Online (Sandbox Code Playgroud)
资源:
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; }
}
Run Code Online (Sandbox Code Playgroud)
控制器:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
映射配置文件:
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<MainObject, MainObjectResource>();
CreateMap<SubItem, SubItemResource>();
CreateMap<MainObject, MainObjectResource>().ReverseMap()
.ForMember(m => m.Id, opt => opt.Ignore())
.ForMember(m => m.SubItems, opt => opt.Ignore())
.AfterMap((mr, m) => {
//To remove
List<MainObject> removedSubItems = m.SubItems.Where(si => !mr.SubItems.Any(sir => si.Id == sir.Id)).ToList();
foreach (SubItem si in removedSubItems)
m.SubItems.Remove(si);
//To add
List<SubItemResource> addedSubItems = mr.SubItems.Where(sir => !m.SubItems.Any(si => si.Id == sir.Id)).ToList();
foreach (SubItemResource sir in addedSubItems)
m.SubItems.Add( new SubItem {
Value = sir.Value,
});
// To update
List<SubItemResource> updatedSubItems = mr.SubItems.Where(sir => m.SubItems.Any(si => si.Id == sir.Id)).ToList();
SubItem subItem = new SubItem();
foreach (SubItemResource sir in updatedSubItems)
{
subItem = m.SubItems.SingleOrDefault(si => si.Id == sir.Id);
subItem.Value = sir.Value;
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
我在这里做的是一个自定义映射,但我觉得这是一个通用的案例,我希望 AutoMapper 能够通过一些扩展来处理这个问题。我看过一些示例,其中映射配置文件使用自定义映射 (.AfterMap),但实际映射是由 AutoMapper 的静态实例完成的。我不确定这是否适合我通过依赖注入使用 AutoMapper:我不是一个有经验的程序员,但对我来说似乎不太合适。
感谢 Ivan Stoev,我开始研究AutoMapper.Collection,这确实是我希望找到的扩展。在实施我的列表后,我会按照我的意愿进行更新。配置在我的使用中很简单,因为我只需要指定我的对象的 Id。
我的启动配置改为:
using AutoMapper;
using AutoMapper.EquivalencyExpression;
[....]
public void ConfigureServices(IServiceCollection services)
{
services.AddAutoMapper(cfg => {
cfg.AddCollectionMappers();
});
}
[....]
Run Code Online (Sandbox Code Playgroud)
还有我的映射配置文件:
CreateMap<SubItem, SubItemResource>().ReverseMap()
.EqualityComparison((sir, si) => sir.Id == si.Id);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4714 次 |
| 最近记录: |