C# 使用 Automapper 将 DTO 映射到实体

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13156437/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 01:47:50  来源:igfitidea点击:

Mapping a DTO to an Entity with Automapper

c#entity-frameworkautomapper

提问by Paul Aldred-Bann

I have an Entity Framework POCO with the following structure.

我有一个具有以下结构的实体框架 POCO。

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

I've created a Data Transfer Object for this entity to be used by my views.

我为这个实体创建了一个数据传输对象,供我的视图使用。

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

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

现在,我的 Global.asax 文件中有以下映射代码。

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

Everything is working fine, I pass the DTO to my views OK and I can create a new instance of Entityfrom my EntityDtomodel. The problem arises when I try to edit my Entity; I'm aware this is down to AutoMapper losing the Entity Key that EF creates to track changes to the object, but having read through a few sources there doesn't seem to be a definitive solution. Here is the action I'm using to edit my entity.

一切正常,我将 DTO 传递给我的视图 OK,我可以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);
}

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

现在,我该怎么做才能解决这个问题?我可以吗:

  1. Somehow tell AutoMapper to .Ignore()the Entity Key properties?
  2. Get AutoMapper to copy out the Entity Key properties?
  3. .Attach()my mapped Entityand set the state to modified?
  1. 以某种方式告诉 AutoMapper.Ignore()实体键属性?
  2. 获取 AutoMapper 以复制实体键属性?
  3. .Attach()我的映射Entity并将状态设置为已修改?

Any help always appreciated.

任何帮助总是很感激。

采纳答案by Pluc

.Attach() my mapped Entity and set the state to modified?

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

Where is your context instantiated? You should do that in your EditEntity action imo.

您的上下文在哪里实例化?您应该在您的 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);
    }
}

回答by dark_ruby

Try passing entity as a second parameter to your mapping.

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

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

Otherwise, your entity instance is overwritten with a new instance, and you lose the entity created in the first line.

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

回答by SventoryMang

An alternative answer that doesn't require Automapper for the DTO to Entity conversion is using a DbEntry:

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

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

        oldEntry.CurrentValues.SetValues(updatedEntity);

You don't need any attach/state checking because you are getting the old entity first so it has change tracking attached to it. Also, the CurrentValues.SetValues can accept a different type, in this example updatedEntity is the DTO. Set Values documentation is explained as such:

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

Sets the values of this dictionary by reading values out of the given object. The given object can be of any type. Any property on the object with a name that matches a property name in the dictionary and can be read will be read. Other properties will be ignored. This allows, for example, copying of properties from simple Data Transfer Objects (DTOs).

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

So seems like it already can perform in an automapper-esque way.

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