C# 使用Automapper将DTO映射到实体
我有一个实体框架POCO,其结构如下C# 使用Automapper将DTO映射到实体,c#,entity-framework,automapper,C#,Entity Framework,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; } }
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?
现在,我该怎么解决这个问题呢?我可以:
.Ignore()
.Attach()
my mappedEntity
并将状态设置为modified感谢您的帮助。尝试将实体作为第二个参数传递给映射
entity = Mapper.Map<EntityDto, Entity>(model, entity);
entity=Mapper.Map(模型,实体);
否则,您的实体实例将被新实例覆盖,并且您将丢失在第一行中创建的实体
.Attach()我的映射实体并将状态设置为修改
public ActionResult编辑实体(实体到模型)
{
var entity=Mapper.Map(模型);
context.Set().Attach(实体);/(或context.entity.Attach(实体);)
context.Entry(entity).State=System.Data.EntityState.Modified;
SaveChanges();
返回视图(模型);
}
您的上下文在哪里实例化?您应该在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);
}
}
public ActionResult编辑实体(实体到模型)
{
使用(var context=new MyContext())
{
var entity=Mapper.Map(模型);
context.Set().Attach(实体);/(或context.entity.Attach(实体);)
context.Entry(entity).State=System.Data.EntityState.Modified;
SaveChanges();
返回视图(模型);
}
}
DTO到实体转换不需要Automapper的另一个答案是使用DbEntry:
var oldEntity = DbSet.FirstOrDefault(x => x.Id == updatedEntity.Id);
var oldEntry = Context.Entry(oldEntity);
oldEntry.CurrentValues.SetValues(updatedEntity);
您不需要任何附加/状态检查,因为您首先获取旧实体,因此它附加了更改跟踪。此外,CurrentValues.SetValues可以接受不同的类型,在本例中,updateEndity是DTO。设定值文档解释如下:
通过读取给定对象的值来设置此字典的值。给定对象可以是任何类型。将读取对象上的任何属性,其名称与字典中的属性名称匹配并且可以读取。其他属性将被忽略。例如,这允许从简单数据传输对象(DTO)复制属性
看来它已经可以像automapper那样执行了。不幸的是,我已经尝试过了,导致了相同的问题-基本上automapper说它找不到映射配置,就像我从上下文中检索我的
实体时一样,这不再只是您的平均POCO,因此AutoMapper不知道该做什么。如果实体上有其他属性您还没有列出,您最好告诉AutoMapper忽略它们:。FormMember(dest=>dest.PropertyToIgnore,opt=>opt.UseDestinationValue)这就是问题所在,在我创建AutoMapper映射时,实体只是一个POCO,因此不包含EF在检索时创建的任何额外实体内容,所以我不能告诉AutoMapper忽略它们。天哪,我不知道你可以用Map做这件事。太棒了。@dark_ruby非常感谢你,它解决了我的问题。太棒了,这刚刚奏效。给我一些时间来尝试我的实际项目。很高兴我可以alt tab并复制粘贴。。我的意思是帮助你这对我完全有效。Mapper.Map(model,entity)解决方案对我不起作用,因为当你有一个嵌套的实体时,你会更新它(因此你的属性现在引用一个不同的(已经被跟踪的)实体),automapper解决方案会“覆盖”以前引用的实体,changetracker会抱怨它已经在跟踪一个具有该标识符的实体。
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);
}
}
var oldEntity = DbSet.FirstOrDefault(x => x.Id == updatedEntity.Id);
var oldEntry = Context.Entry(oldEntity);
oldEntry.CurrentValues.SetValues(updatedEntity);