Mapping a DTO for an object using Automapper

I have an Entity Framework POCO framework with the following structure.

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

I created a data transfer object for this object that will be used by my views.

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

Now I have the following conversion code in my Global.asax file.

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

Everything works fine, I pass the DTO to my OK views, and I can create a new Entity instance from my EntityDto model. The problem occurs when I try to change my Entity ; I know this is before AutoMapper, which lost the Entity key that EF creates to track object changes, but after reading a few sources, it does not seem to be the final solution. Here is the action I use to edit my 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); } 

Now, what should I do to solve this problem? Can I:

  • How to say AutoMapper for .Ignore() properties of an Entity Key object?
  • Get AutoMapper to copy Entity Key object properties?
  • .Attach() my associated Entity and set the state to change?

Any help is always appreciated.

+7
source share
3 answers

.Attach () is my mapped entity and given state changed?

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

Where is your context created? You must do this in your EditEntity imo action.

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

Try passing the object as the second parameter for your mapping.

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

Otherwise, the instance of your object will be overwritten with the new instance, and you will lose the object created on the first line.

+12
source

An alternative answer that Automapper does not require to convert DTO to Entity uses DbEntry:

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

You do not need to check for the presence / status, because you first get the old entity, so change tracking is attached to it. In addition, CurrentValues.SetValues ​​can accept different types, in this example updatedEntity is a DTO. The documentation for the value values ​​is explained as follows:

Sets the values ​​of this dictionary by reading the values ​​from the specified object. This object can be of any type. Any property of an object with a name that matches the property name in the dictionary and can be read will be read. Other properties will be ignored. This allows, for example, copying properties from simple data transfer objects (DTO).

It looks like it can already work in automapper-esque style.

+1
source

All Articles