【问题标题】:ASP.net MVC - Should I use AutoMapper from ViewModel to Entity Framework entities?ASP.net MVC - 我应该使用从 ViewModel 到实体框架实体的 AutoMapper 吗?
【发布时间】:2011-09-28 20:02:03
【问题描述】:

我目前正在使用 AutoMapper 将我的 Entity Framework 实体映射到我的视图模型:

public class ProductsController : Controller
{
    private IProductRepository productRepository;

    public ProductsController(IProductRepository productRepository)
    {
         this.productRepository = productRepository;
    }

    public ActionResult Details(int id)
    {
        var product = productRepository.GetProduct(id);

        if( product == null )
            return View("NotFound");

        ProductDetailsViewModel model = Mapper.Map<Product, ProductDetailsViewModel>(product);

        return View(model);
    }
}

这很好用。我的问题是何时需要从视图模型转到实体以更新数据库。我应该为此使用 AutoMapper 吗?这是一种不良/危险的做法吗?

AutoMapper 似乎很适合将复杂类型展平为简单(平面)类型,但到目前为止,我正在努力尝试从平面/简单类型转变为更复杂的类型,例如具有各种导航属性的实体.

如果使用 AutoMapper 执行此操作不是一个好主意,那么我的代码对于 Create 操作会是什么样子?

public ActionResult Create(CreateProductViewModel model)
{
    if( ModelState.IsValid )
    {
        // what do i do here to create my Product entity?
    }
}

编辑操作呢?

public ActionResult Edit(int id, EditProductViewModel model)
{
    Product product = productRepository.GetProduct(id);

    // how do i convert my view model to my entity at this point???
}

【问题讨论】:

标签: c# asp.net-mvc entity-framework automapper


【解决方案1】:

我认为更新您的实体是一件相当大的事情,并且不应该使用任何自动化工具。手动设置属性。

是的,它的代码量非常小,但自动映射器或在数据库实体上运行 updatemodel 有时会产生意想不到的后果。最好确保您的写入正确完成。

【讨论】:

  • 这个我很好,但是这种让我的控制器变得丑陋了。我的心态是控制器应该尽可能简单(只有几行长)。我应该把它吸起来吗? :)
  • @Dismissile - 所以不要将代码放在控制器中。创建一个负责在视图模型和实体之间进行转换的类,并从控制器中调用它。使测试更容易并遵守 SRP。
  • 您知道您可以自定义映射以完全按照您希望它为每个属性执行的操作。我真的看不出这与编写自己的赋值语句之间有什么区别。对于简单的属性到属性的映射,我认为效果很好。
  • +1 到 jfar。告诉不要问。使用 automapper 是在问你是否问我。还要让它尽可能简单,并尽可能多地排除框架依赖。
  • @tvanfosson - 这比写Model.Property = ViewModel.Property所需的秒数还要多
【解决方案2】:

本质上自动映射是不好的,我在这个http://blog.gavryli.uk/2015/12/02/why-automapping-is-bad-for-you/上写了一篇博文

【讨论】:

  • 答案中的链接已损坏,新链接似乎是ivanazure.wordpress.com/2015/12/02/… 为什么所有反对票?这篇文章给出了反对自动映射的有力论据。
  • 关于自动映射失败的绝佳替代视角,不用担心反对票。我建议在您的回答中包含您的一些观点。
【解决方案3】:

我将 AutoMapper 与一个专门的映射类一起使用,该类了解如何从一个简单的模型制作一个复杂的模型。 AutoMapper 用于处理一对一映射和类中的自定义逻辑,以完成更复杂的事情(如关系等)。所有的 AutoMapper 配置都是在映射类的静态构造函数中完成的,它还验证映射配置,以便错误尽早失败。

public class ModelMapper
{
    static ModelMapper()
    {
        Mapper.CreateMap<FooView,Foo>()
              .ForMember( f => f.Bars, opt => opt.Ignore() );

        Mapper.AssertConfigurationIsValid();
    }

    public Foo CreateFromModel( FooView model, IEnumerable<Bar> bars )
    {
         var foo = Mapper.Map<FooView,Foo>();
         foreach (var barId in model.BarIds)
         {
             foo.Bars.Add( bars.Single( b => b.Id == barId ) );
         }
         return foo;
    }
}

【讨论】:

    【解决方案4】:

    您也可以尝试将 AutoMapper 配置为仅映射标量属性(而不是必须 .Ignore() 映射您不希望的每个属性(包括继承的属性,如 .EntityKey.EntityState)。

    AutoMapper.Mapper.CreateMap<EntityType, EntityType>()
        .ForAllMembers(o => {
             o.Condition(ctx =>
                 {
                     var members = ctx.Parent.SourceType.GetMember(ctx.MemberName); // get the MemberInfo that we are mapping
    
                    if (!members.Any())
                        return false;
                    return members.First().GetCustomAttributes(typeof(EdmScalarPropertyAttribute), false).Any(); // determine if the Member has the EdmScalar attribute set
                });
        });
    

    更多信息http://www.prosoftnearshore.com/blog/post/2012/03/14/Using-AutoMapper-to-update-Entity-Framework-properties.aspx

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多