Eine bedeutende Hamburger Behörde beauftragte die HanseVision mit der Konzeption und Neuentwicklung von diversen veralteten Verfahren, die in einem Projektfenster von drei Jahren umgesetzt werden sollen. Die insgesamt fünf resultierenden Lösungen wurden iterativ mit den neusten Webtechnologien umgesetzt.

Als Webtechnologie kam bei der Umsetzung ASP.NET MVC zum Einsatz, welche über das ADO.NET Entity Framework mit der Datenbasis (SQL Server) kommuniziert. In der Benutzeroberfläche sorgen jQuery und Komponenten wie bspw. DataTables für noch mehr Anwenderzufriedenheit.

Um einen modularen, wartbaren Aufbau der Anwendungen zu gewährleisten, wurden eine Systemarchitektur bestehend aus mehreren Schichten gewählt und umgesetzt.

 

Schicht

Typ

Front-end horizontal
Businesslogik horizontal
Datenzugriffsschicht horizontal
Datenbasis horizontal
Common runtime vertikal

 

Um die Daten komfortabel durch die Schichten der Anwendung transportieren zu können, habe ich mich dazu entschieden, die Entitäten als POCO-Klassen (Plain Old CLR Object) in eine vertikale Schicht auszulagern, die von allen horizontalen Schichten referenziert werden kann. Bei Anwendungen, die einen sehr starken Datenbankcharakter haben – d.h. die meisten Felder in den Datenbank-Tabellen werden auch zur Anzeige in der UI gebracht- können diese POCO-Klassen u.a. auch als View Model verwendet werden.

Wie POCO-Klassen aus dem EDMX generiert werden können, zeigt u.a. dieser Artikel: http://blogs.msdn.com/b/adonet/archive/2010/01/25/walkthrough-poco-template-for-the-entity-framework.aspx

In meinen Projekten wurde das T4-Template derart angepasst, dass es die POCO-Klassen nicht im selben Projekt (wie der EDMX), sondern unterhalt des Common-Projektes generiert werden.

 

Vorteil

Durch das Auslagern der POCO-Klassen in eine vertikale Schicht und deren Nutzung las Datentransfer-Objekte, kann man sich ein kompliziertes Mapping zwischen den Objekten der einzelnen Schichten sparen. (Bei jeder Änderung an einer Entität müsste ansonsten zusätzlich auch das Mapping zwischen “Data Access Object” und “Business Object” sowie zwischen “Business Object” und “View Model” angepasst werden.)

 

Nachteile

Der Nachteil bei diesem Ansatz liegt in dem Umstand, dass man im Zweifel zu viele oder zu wenigen Eigenschaften für eine konkrete View im Gepäck hat.

Hat eine POCO-Klasse bspw. mehr Eigenschaften als in der Editier-Ansicht dargestellt werden sollen, dann muss man diese “überschüssigen” Eigenschaften als “Hidden Fields” durchreichen, da diese Werte ansonsten bei der nächsten Speicheraktion verloren gehen. Das impliziert einen relativ hohen Pflegeaufwand in den Views bei häufigen Änderungen an den Entitäten in der Datenbasis.

Werden andererseits in einer View zusätzliche Felder verlangt, dann müssen diese im Zweifel in einer Partial Class ergänzt werden, was natürlich auch nicht unbedingt schön ist.

 

Daher AutoMapper

Wegen der oben genannten Nachteile strebt man bei der Entwicklung mit ASP.NET MVC immer ein möglichst exakt zugeschnittenes View Model an. Weichen also POCO-Klasse und View-Anforderungen zu stark ab, dann macht es auf jeden Fall Sinn ein separates View Model zu erstellen.  Mit einem separaten View Model entsteht dann aber die Notwendigkeit ein Mapping zwischen POCO-Klasse und View Model zu definieren.

Damit das Erstellen der Mappings nicht die Aufwände und die Nerven belastet, können kleine Helfer wie die Komponente “AutoMapper” (http://automapper.codeplex.com/) eingesetzt werden. AutoMapper verknüpft gleichnamige und Typen-gleiche Eigenschaften zwischen zwei Objekten automatisch. Im Mapping muss also nur das Delta zwischen den Objekten expliziert definiert werden.

Hier ein schlankes Beispiel:

           

 AutoMapper.Mapper.CreateMap<BookBusinessData, BookViewModel  >()
                .ForMember(dest => dest.DoShowDialog, opts => opts.Ignore())
                .ForMember(dest => dest.Author, opts => opts.MapFrom(src => String.Format("{0} (Ranking: {1})", src.Author, src.Ranking.ToString())));

 

Alle Eigenschaften außer “DoShowDialog” und “Author” werden automatisch verknüpft. Eigentlich wird auch “Author” automatisch verknüpft. In diesem Fall soll aber das View Model einen Wert für “Author” bekommen, der sich aus mehreren Felder zusammensetzt.

Die Eigenschaft “DoShowDialog” wird beim Mapping komplett ignoriert und die Eigenschaft “Author” wird – wie zuvor bereits erwähnt – mit mehreren Werten aus dem Business-Objekt belegt. Für eine richtig komplexe Mapping-Logik bietet AutoMapper die Methode “AfterMap” in der dann frei definierter Code das Mapping sicherstellt.

Das Erstellen dieser “Maps” muss einmal zur Laufzeit sichergestellt werden, bevor folgender Aufruf  beispielhaft ein Business Objekt mit einem View Model verbindet.

 
BookViewModel
book  = AutoMapper.Mapper.Map< BookViewModel>(businessObject);

Ein guter Platz für das Erstellen der Mappings wäre daher bspw. die Global.asax oder eine Singleton-Implementierung, die das Erstellen gewährleistet.

 

Also, falls Ihr mal wieder ein ASP.NET MVC Projekt habt, macht Euch frühzeitig Gedanken über Anzahl und Komplexität der View Models. Wenn Ihr auf Grund zu starker Abweichung von den Entitäten viele neue View Models erstellen müsst, dann prüft doch mal, ob AutoMapper Euch helfen kann. 🙂   

Leave a comment

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Time limit is exhausted. Please reload the CAPTCHA.