2011-09-28 8 views
18

Obecnie używam AutoMapper mapować moje podmioty Entity Framework do mojego widoku modelu:ASP.net MVC - Czy powinienem używać AutoMapper z ViewModel do encji 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); 
    } 
} 

Działa to dobrze. Mam pytanie, kiedy muszę przejść z mojego modelu widoku do mojej jednostki, aby zaktualizować bazę danych. Czy powinienem używać do tego AutoMappera? Czy to jest zła/niebezpieczna praktyka?

Wygląda na to, że AutoMapper jest dobry do spłaszczania złożonego typu do prostego (płaskiego) typu, ale jak na razie staram się przejść od płaskiego/prostego do bardziej złożonego typu, jak moja istota z różnymi nawigacjami nieruchomości.

Jeśli nie jest dobrym pomysłem, aby użyć AutoMappera, to jaki byłby mój kod dla akcji Create?

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

Co należy zrobić w akcji edycji?

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

Twoje wizjery mogą mieć własność produktu Produkt, w ten sposób nie będziesz musiał konwertować w ogóle. – Joakim

+0

Ten artykuł zawiera kilka sugestii. http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/ – jrummell

Odpowiedz

25

jestem od myślenia, że ​​aktualizowanie jednostek jest dość wielkiego i że nie powinno być zautomatyzowane narzędzie kiedykolwiek. Ustaw właściwości ręcznie.

Tak, to bardzo mała ilość więcej kodu, ale automapper lub uruchomiony updatemodel na obiektach bazy danych może czasami mieć niezamierzone konsekwencje. Lepiej upewnić się, że twoje zapisy są wykonane poprawnie.

+0

W porządku, ale ten rodzaj sprawia, że ​​mój kontroler jest brzydszy. Rozumiem, że kontroler powinien być tak prosty, jak to tylko możliwe (tylko kilka linii). Czy powinienem to po prostu wyssać? :) – Dismissile

+0

+1. Automapper i jego funkcje doskonale nadają się do spłaszczania obiektów do modeli podglądu, ale musisz trochę lepiej przemyśleć elementy. –

+4

@ Dismissile - więc nie umieszczaj kodu w kontrolerze. Utwórz klasę odpowiedzialną za konwersję między viewmodels a encjami i wywołaj ją ze sterownika. Sprawia, że ​​testowanie jest łatwiejsze i przylega do SRP. –

10

Używam AutoMapper z wyspecjalizowaną klasą odwzorowania, która rozumie, jak zrobić złożony model z prostego. AutoMapper jest używany do obsługi mapowania typu jeden do jednego i niestandardowej logiki w klasie do robienia bardziej złożonych rzeczy (takich jak relacje itp.). Cała konfiguracja AutoMapper jest wykonywana w konstruktorze statycznym dla klasy mapowania, która również sprawdza poprawność konfiguracji odwzorowania, aby błędy zawodziły wcześniej.

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

Można również spróbować konfiguracji AutoMapper tylko map właściwości skalarnej (zamiast .Ignore() każda nieruchomość nie chcesz go (w tym dziedzicznych właściwości jak .EntityKey i .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 
      }); 
    }); 

Niektóre więcej informacji na http://www.prosoftnearshore.com/blog/post/2012/03/14/Using-AutoMapper-to-update-Entity-Framework-properties.aspx

0

Zasadniczo automapping jest zły, pisałem na blogu o tym http://blog.gavryli.uk/2015/12/02/why-automapping-is-bad-for-you/

+1

Link w odpowiedzi jest zepsuty, nowy wydaje się być https://ivanazure.wordpress.com/2015/12/02/ dlaczego-automapie-to-złe-dla-ciebie/ Dlaczego wszystkie spadki? Artykuł zawiera świetne argumenty przeciwko automatyzacji. – Gebb

Powiązane problemy