使用AutoMapper和EFCore跟踪变化时将DTO映射到实体

对于AutoMapper和EFCore来说,这是一个非常新颖的东西,因此可能会咬掉更多的东西,但我认为我会放弃它,但是失败了,也许它不可能,但如果可能有人能指引我正确的方向。使用AutoMapper和EFCore跟踪变化时将DTO映射到实体

我正在使用AutoMapper将我的实体转换为DTO,这很好。

现在我想将我的DTO转换为实体并让EntityFramework跟踪所有更改(属性更新,从列表中删除子对象等),但是这可能吗?

所以,如果我有一个简单的PUT方法,我想这样做,并让automapper理清其余

public async Task<IActionResult> PutAsync([FromBody] MyDTO model) 
{ 
    // GET OBJECT FROM DATABASE HERE 
    var dbValue = _repos.GetMyObjectUsingId(999); 

    // apply updates 
    _mapper.Map<MyDTO, MyObject>(dbValue, model); 

} 

回答

0

您可以创建一个适配器类,以便您的变更集仍然是相同的: 你有没有DTO的继承接口

假设你有一个DTO:

public interface IFooDTO 
{ 
    int Id { get; set;} 
    string Name { get; set;} 
} 

public class FooDTO : IFooDTO 
{ 
    public int Id { get; set;} 
    public string Name { get; set; } 
} 

然后你有你的实体

public class FooEntity 
{ 
    public int Id; 
    public string name; 
} 

然后创建您的适配器像这样从foo的接口继承:

public class FooAdapter : IFooDTO 
{ 
    FooEntity entity; 
    FooAdapter(FooEntity entity) 
    { 
     this.entity = entity; 
    } 

    public int Id 
    { 
     get {return this.entity.Id;} 
     set {/*Do nothing set by EF*/} 
    } 

    public string Name 
    { 
     get {return this.entity.Name;} 
     set {this.entity.Name = value; } 
    } 

    public void Apply(FooDTO foo) 
    { 
     //I don't remember if this is the correct order but you get the gyst 
     this._mapper.Map<IFooDTO, IFooDTO>(this, foo); 
    } 
} 

然后你只需要你在映射DTO从您的Idto地图。

用法:

public ActionResult PutFoo(int id, FooDTO foo) 
{ 
    var entity = context.Foos.FirstOrDefault(x => x.Id == id); 
    var adapter = new FooAdapter(entity); 
    adapter.Apply(foo); 
    //Entity has been updated and has original changes 
} 

编辑

儿童做工精细只是使用相同的适配器模式这个二传手是一个很大的代码,但

public BarDTO childBar 
{ 
    get { return new BarAdapter(this.entity.Bar).ToDTO(); } 
    set { new BarAdapter(this.entity.Bar).Apply(value) } 
} 

同步处理的实体:

public static void Sync<TEntity, TEntityKey, TDTO>(this ICollection<TEntity> entityCollection, ICollection<TDTO> dtoCollection, 
    Func<TEntity> entityConstructor, Action<TDTO, TEntity> copyAction, 
    Action<TEntity> onDeleteAction, 
    Func<TEntity, TEntityKey> entityKeySelector, 
    Func<TDTO, TEntityKey> dtoKeySelector) 
    where TEntity : class 
    where TEntityKey : struct 
{ 
    dtoCollection = dtoCollection ?? new TDTO[] { }; 
    except = except ?? new TEntityKey[] { }; 

    var dtoIds = dtoCollection.Select(dto => dtoKeySelector(dto)).ToHashSet(); 
    foreach (var entity in entityCollection.Where(x => false == dtoIds.Contains(entityKeySelector(x))).ToArray()) 
    { 
     onDeleteAction(entity); 
     entityCollection.Remove(entity); 
    } 

    var entityCollectionMap = entityCollection.ToDictionary(x => entityKeySelector(x)); 

    foreach (var dtoItem in dtoCollection) 
    { 
     TEntity entity = null; 
     if (dtoKeySelector(dtoItem).HasValue) 
     { 
      entity = entityCollectionMap.ContainsKey(dtoKeySelector(dtoItem)) ? entityCollectionMap[dtoKeySelector(dtoItem)] : default(TEntity); 

     } 

     if (null == entity) 
     { 
      entity = entityConstructor(); 
      entityCollection.Add(entity); 
     } 
     copyAction(dtoItem, entity); 
    } 
} 

转 http://cn.voidcc.com/question/p-nfroylah-bmu.html
posted @   dreamw  阅读(403)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
历史上的今天:
2021-06-22 mysql安装之初始化报错:mysqld: [ERROR] Found option without preceding group in config file G:\mysql\my.ini at
2021-06-22 .NET面试题大全(C#面试题)2020更新
2021-06-22 mysql 高版本 sql_mode=only_full_group_by 问题解决方法
2021-06-22 Mysql8.0出现this is incompatible with sql_mode=only_full_group_by
2021-06-22 mysql8 设置sql_mode后不能启动
2021-06-22 mysql.ini 配置
2021-06-22 解决Mysql安装之后没有my.ini配置文件问题
点击右上角即可分享
微信分享提示