12

我有一个具有以下结构的实体框架 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 传递给我的视图,我可以Entity从我的EntityDto模型创建一个新实例。当我尝试编辑我的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并将状态设置为已修改?

任何帮助总是很感激。

4

3 回答 3

21

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

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

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

于 2012-10-31T11:12:06.140 回答
11

.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);
    }
}
于 2012-10-31T11:26:32.903 回答
4

不需要 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。设置值文档解释如下:

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

所以似乎它已经可以以自动映射器式的方式执行。

于 2016-09-27T20:41:17.537 回答