我有一个实体框架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);
}
现在,我该怎么做才能解决这个问题? 我可以吗:
- 不知怎的告诉AutoMapper到
.Ignore()
实体键的属性? - 获得AutoMapper复制了实体键的属性?
-
.Attach()
我的映射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行动海事组织。
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);
}
}
尝试通过实体作为第二个参数的映射。
entity = Mapper.Map<EntityDto, Entity>(model, entity);
否则,你的实体实例是覆盖一个新实例,你失去了在第一行创建的实体。
不需要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的)属性的复制。
所以看起来它已经可以在automapper式的方式进行。