繁体   English   中英

使用Automapper将DTO映射到实体

[英]Mapping a DTO to an Entity with Automapper

我有一个具有以下结构的实体框架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时出现问题; 我知道这是由于AutoMapper丢失了EF创建的用于跟踪对象更改的实体密钥,但是通读了一些资料后,似乎并不是一个确定的解决方案。 这是我用来编辑实体的动作。

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);
}

现在,我该怎么解决呢? 我可以吗:

  1. 以某种方式告诉AutoMapper .Ignore()实体键属性?
  2. 获取AutoMapper来复制实体键属性?
  3. .Attach()我的映射Entity并将状态设置为已修改?

任何帮助总是感激不尽。

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

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

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

.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);
    }
}

对于DTO到实体的转换,不需要Automapper的另一种答案是使用DbEntry:

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

        oldEntry.CurrentValues.SetValues(updatedEntity);

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

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

看起来它已经可以像自动映射器一样执行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM