首页 文章

使用Automapper将DTO映射到实体

提问于
浏览
8

我有一个具有以下结构的实体框架POCO .

public class Entity
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
}

我为这个实体创建了一个数据传输对象供我的视图使用 .

public class EntityDto
{
    public int Id { get; set; }
    public string Name { get; set; }
}

现在,我在Global.asax文件中有以下映射代码 .

Mapper.CreateMap<Entity, EntityDto>();
Mapper.CreateMap<EntityDto, Entity>(); // not sure whether I need this as well?

一切正常,我将DTO传递给我的观点确定,我可以从我的 EntityDto 模型中创建 Entity 的新实例 . 当我尝试编辑 Entity 时出现问题;我似乎是一个明确的解决方案 . 这是我用来编辑我的实体的动作 .

public ActionResult EditEntity(EntityDto model)
{
    var entity = context.Entities.Single(e => e.Id == model.Id);
    entity = Mapper.Map<EntityDto, Entity>(model); // this loses the Entity Key stuff
    context.SaveChanges();

    return View(model);
}

现在,我该怎么做才能解决这个问题?我可以吗:

  • 以某种方式告诉AutoMapper .Ignore() 实体密钥属性?

  • 获取AutoMapper以复制实体密钥属性?

  • .Attach() 我的映射 Entity 并将状态设置为已修改?

任何帮助总是赞赏 .

3 回答

  • 13

    .Attach()我映射的实体并将状态设置为修改?

    public ActionResult EditEntity(EntityDto model)
    {
        var entity = Mapper.Map<Entity>(model);
        context.Set<Entity>().Attach(entity); // (or context.Entity.Attach(entity);)
        context.Entry<Entity>(entity).State = System.Data.EntityState.Modified;
        context.SaveChanges();
        return View(model);
    }
    

    您的上下文在哪里实例化?你应该在EditEntity动作imo中这样做 .

    public ActionResult EditEntity(EntityDto model)
    {
        using(var context = new MyContext())
        {
            var entity = Mapper.Map<Entity>(model);
            context.Set<Entity>().Attach(entity); // (or context.Entity.Attach(entity);)
            context.Entry<Entity>(entity).State = System.Data.EntityState.Modified;
            context.SaveChanges();
            return View(model);
        }
    }
    
  • 8

    尝试将实体作为第二个参数传递给您的映射 .

    entity = Mapper.Map<EntityDto, Entity>(model, entity);
    

    否则,您的实体实例将被新实例覆盖,并且您将丢失在第一行中创建的实体 .

  • 1

    另一个不需要Automapper进行DTO到实体转换的答案是使用DbEntry:

    var oldEntity = DbSet.FirstOrDefault(x => x.Id == updatedEntity.Id);
            var oldEntry = Context.Entry(oldEntity);
    
            oldEntry.CurrentValues.SetValues(updatedEntity);
    

    您不需要任何附加/状态检查,因为您首先获取旧实体,因此它附加了更改跟踪 . 此外,CurrentValues.SetValues可以接受不同的类型,在此示例中,updatedEntity是DTO . Set Values文档解释如下:

    通过读取给定对象的值来设置此字典的值 . 给定对象可以是任何类型 . 将读取对象上具有与字典中的属性名称匹配且可以读取的名称的任何属性 . 其他属性将被忽略 . 例如,这允许从简单的数据传输对象(DTO)复制属性 .

    所以它似乎已经可以以自动化程序的方式执行 .

相关问题