2011-09-28 56 views
18

我目前使用AutoMapper到我的实体框架的实体映射到我的视图模型:ASP.net MVC - 我应该使用从ViewModel到实体框架实体的AutoMapper?

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要做到这一点,那么将我的代码看起来像一个创建行动是什么?

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??? 
} 
+0

您的ViewModels能有实体产品的属性,这样你就不必在所有转换。 – Joakim

+0

本文提供了一些建议。 http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/ – jrummell

回答

25

我是一个心态的,更新你的实体是一个相当大的交易,并且没有自动工具应该永远使用。手动设置属性。

是它的更多的代码,但automapper或数据库实体运行的UpdateModel一个非常小的量有时会产生意想不到的后果。最好确保你的写入是正确完成的。

+0

我很好这一点,但这种让我的控制器超越难看。我的想法是控制器应该尽可能简单(只有几行)。我应该吮吸它吗? :) – Dismissile

+0

+1。 Automapper及其流派很适合将实体扁平化为视图模型,但您需要对更新实体进行更多考虑。 –

+4

@Dismissile - 所以不要把代码放在控制器中。创建一个负责在视图模型和实体之间转换的类,并从控制器调用它。使测试更轻松并坚持SRP。 –

10

我使用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; 
    } 
} 
2

您也可以尝试配置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

0

一些更多的信息本质上自动映射是坏的,我写了一篇关于这个http://blog.gavryli.uk/2015/12/02/why-automapping-is-bad-for-you/

0博客文章周
+1

答案中的链接已损坏,新的链接似乎是https://ivanazure.wordpress.com/2015/12/02/ why-automapping-is-bad-for-you/ 为什么所有的downvotes?这篇文章给出了很多反对自动映射的论点。 – Gebb