| 

.NET C# Java Javascript Exception

10
Edit: Kleiner Vorweg-Einschub meinerseits, da der Thread hier schon einige Views hat und die Frage doch wohl gar nicht so blöd zu sein scheint :)

Ich habe nochmal ein wenig Quergelesen und denke, ich kann die Frage jetzt recht kurz zusammenfassen und vielleicht wird meine Frage ja verständlicher:

Mit dem "ADO.net POCO Entity Generator" (T4-Template) kann man sich ja POCO aus dem EDMX erstellen lassen. Sind diese POCOs dann eher als

    - Entities im Data Access Layer oder
    - als DTO's/Models im Business Layer
zu betrachten?

Je nachdem müsste man sie halt nochmal im Model kapseln oder auch nicht. Zumindest denke ich, das man es so sehen kann.



Guten Morgen,

ich hätte da mal eine Sammlung von Fragen zu der ich mal einen Meinungsaustausch bräuchte, da meine Google-Suche leider keinen einschlagenden Gedankenblitz brachte. Allerdings bin ich gestern auf diesen Blog hier gestossen der in Anfängen dieselbe Frage stellt: To Wrap or not to Wrap


Es dreht sich hier um die Vorgehensweise in einer WPF-MVVM-Anwendung sowie der Folgefrage inwieweit man EntityObjects vom EF oder eher POCO-Klassen (meine Präferenz) einsetzt, und ob man letztere erweitern oder doch nochmal extra kapseln sollte. Ich versuche es mal zusammenzufassen:

Wrappen oder durchleiten?
Angenommen wir haben einen CustomerView und ein CustomerViewModel und ich möchte Vorname, Nachname, Anschrift etc. aus eine Customer-Model abbilden. Generell gibt es zwei Möglichkeiten:

1. Jede Property nochmal im VM implementieren und dann im Getter/Setter direkt auf _customer.Property verweisen. Hat den Vorteil das man "sauber" implementiert und genau an dieser Stelle auch auf etwaige Korrekturen (Enum zu Int etc.) oder Validierungslogik eingehen kann. Benutze ich das Customer-Model aber in mehreren VM's evtl. sogar Applikationsübergreifend, müsste man eben diese "Korrekturen" überall einbauen.

2. Einfach eine Customer-Property im VM realisieren und direkt das Customer-Model durchleiten. Vorteil für Schreibfaule liegt auf der Hand, soll aber jetzt kein Argument sein. Validierung oder Konvertierung von Enums etc. müsste dann aber im Customer-Model eingebaut werden.

Im o.a. Blog wird dann noch näher auf die Problematik bei Untercollections im Customer-Model eingegangen, hier wird es dann sehr schnell recht ungemütlich und spätestens jetzt bekommt die Fragestellung doch eine Daseinsberechtigung, wie ich finde.

Meine Vermutung ist, das Ihr alle zu 1. raten werdet, eben wegen der sauberen Trennung etc. bzw. antwortet "von Fall zu Fall abwägen". Gut. Denn wäge ich mal ab und habe vielleicht ein paar Stellen, an dem Punkt 2. relativ gefahrlos genutzt werden könnte.

Und hier würde es dann interessanter werden, denn dann müsste ich sämtliche Logik (Validierung, Konvertierung etc.) in das Model mit aufnehmen. Eigentlich finde ich die Idee so schlecht nicht, denn sollten andere Applikationen mit meinem Model arbeiten, dann wären diese elementaren Dinge gleich an der richtigen Stelle, keiner müsste sie doppelt schreiben und vor allem könnte ich sicher sein, das diese Dinge auch korrekt durchgeführt werden.

POCO, EntityObject oder Business-Model
Was wäre dann das Customer-Model in diesem Fall? Die POCO-Klasse oder eine nochmal gekapselte Businessklasse? Möglichkeiten wären ja Folgende:

1. Nutzung eines EDMX mit den daraus generierten EntityObjects
In diesem Fall würde ich nicht im Traum darauf kommen, diese Klassen zu manipulieren. Gut, sie sind als Partial deklariert aber direkt im VM möchte ich sowieso nicht auf ein EntityObject verweisen, denn dann müsste ich im Frontent System.Data.Entity referenzieren und dabei habe ich kein gutes Trennungsgefühl.

2. Nutzung eines EDMX mit per T4 generierten POCO-Klassen
Bei POCO-Klassen hätte ich jetzt keine Sorge, ich kann sie direkt aus dem VM referenzieren ohne hier Verweise aufs EntityFramework setzen zu müssen. In dem Fall wäre die Überlegung, vielleicht auch Validierungslogik und evtl. weiteren Quellcode in die Poco-Klassen zu legen. Vor allem würde dies hier auch INotifyPropertyChanged betreffen.

3. POCO-Klassen die im "BusinessLayer" nochmal gekapselt werden
Dann hätte ich eine nackte T4-Poco-Klasse CustomerPOCO und würde in einer anderen Assembly noch einmal ein CustomerModel erstellen welches die POCO referenziert. Das CustomerModel könnte man dann im VM benutzen.

3a) Dann könnte man doch das Customer-Model auch direkt im VM durchleiten, oder nicht?
3b) Oder auch in diesem Fall dann immer noch sauber alle Properties im VM einzeln implementieren? Mit POCO + Model + VM + Properties erscheint mir das dann verhältnismässig aufwändig. Oder bin ich hier nur zu Faul? :)

Wenn ich im Internet nach Mehrschichtenarchitektur suche, dann fallen in sämtlichen Beispielen zur Geschäftslogik eigentlich immer nur Beispiele zum Erstellen, Löschen von Objekten oder Veraltung von ganzen Collections an (CreateCustomer etc.). Aber Geschäftslogik kann ja durchaus auch umfangreiche Berechnungen z.B. in einem EinkommensteuerModel umfassen. Und hier stelle ich mir wirklich die Frage, ob es nicht praktisch wäre, dann solche Berechnungsfunktionen auch im POCO zu implementieren. Falls ich sowieso zwei Klassen (POCO und Model) benötige, dann könnte ich ja auch auf das POCO verzichten und das EntityObject + Model benutzen. Dann sehe ich da keinen wirklichen Vorteil mehr drin.

Fragen über fragen. Ich hoffe ich hab mein Problem nicht allzu konfus dargestellt und Ihr könnt mir hier ein paar konkretere Ratschläge geben, als ich sie im Netz finde. Es ist nicht so, das ich nicht etliche Blogs oder MSDN-Seiten gelesen hätte. Vielleicht sehe ich den Wald vor lauter Bäumen auch nur gerade nicht.

Lieben Dank.
News:
19.10.2011
Anhalter 61 1 4
1 Antwort
1
Ein kleiner Beitrag von mir:
EnitityObject würde ich nicht verwenden. Diese sind in Hinblick auf verteilte Anwendungen (WCF) nicht brauchbar. Dann stellt sich die Frage POCOs oder STEs. Ich denke, da kommt es auf die Anwendung drauf an, da beides Vor- und Nachteile hat. Siehe z.B. How would I know if I should use Self-Tracking Entities or DTOs/POCOs?
Ich verwende Entities sowohl im DataAccessLayer des Servers als auch im ViewModel des Clients.
Dazwischen werden sie serialisiert und verschickt ;)
19.10.2011
Jürgen Luhr 7,1k 2 9
Danke Jürgen. EntityObjekte möchte ich für mich auch schon einmal grossflächig ausschließen. Verteilte Anwendungen sind (glaube ich) nicht in Planung, wobei man natürlich auch an zukünftige Ereignisse denken sollte. Ich tendiere daher zu POCO, bin nur unklar, ob die diese um Validierung und INotifyPropertyChanged erweitern kann/darf/soll.
Anhalter 19.10.2011
INotifyPropertyChanged wird erforderlich, wenn die POCOs per XAML gebunden sind (Ist bei meiner Anwendung der Fall).
Um was für Validierung handelt es sich?
Die Validierung, ob ein Feld leer sein darf oder nicht (Pflichtfeldprüfung) halte ich persönlich in den Entities für in Ordnung. Komplexere Validierungen gehören in den Businesslayer. Aber vielleicht kannst du deine geplante Validierung noch etwas erläutern.
Jürgen Luhr 19.10.2011
Also leitest Du Deine POCOs im ViewModel direkt per Property an das view weiter? So in der Art {Binding Customer.Nachname}. Das wäre ja eine der Fragen.

Mit Validierung allgemein meine ich Required, StringLenght etc, halt die üblichen Verdächtigen. Wobei ich in (vorläufig, da kommen sicher noch mehr) Fall eine längere Überprüfung habe in der Art "wenn A=x und B=y und C=z dann ist F ein Pflichtfeld oder darf nicht =f sein" Und von der Art hab ich in der Klasse gleich mehrere Kandidaten. Der Code wird momentan in der Item-Property (Default) ausgeführt, da ich IDataErrorInfo nutzen möchte.
Anhalter 19.10.2011
1
Zur ersten Frage: Ja.

Zum zweiten Part: Da wir eine verteilte Anwendung entwickeln, findet die Validierung zwingend auf dem Server im Businesslayer statt. Zusätzlich können auch Validierungen im Client vorkommen, um einen Roundtrip zum Server zu vermeiden, aber wirklich nur solche, die bereits auf dem Server implementiert sind. Meta-Informationen wie Textlänge, Pflichtfeld hinterlege ich als CustomAttributes in den Entities. Das Grundgerüst hierzu erzeuge ich bereits im T4-Template.
Jürgen Luhr 19.10.2011
@Jürgen: Du hast also teilweise Validierungsmassnahmen redundant implementiert? Vermutlich um zu gewährleisten das ein von Dir unabhängig entwickelter Client (z.B. IPhone) keine BL am Server aushebelt, oder? Wie wartest Du das, oder fügst du die *.cs Files mit den Validierungfunktionen per „Add as Link“ im Client Projekt hinzu?
Jorgen Schumann 19.10.2011
Der Grund ist genau dieser (weitere Clients).
"Add as Link" ist da eine Möglichkeit.
In der Regel finden bei mir Validierungen auf dem Server statt, da ich genau diese Redundanz vermeiden möchte
Jürgen Luhr 19.10.2011
@Jürgen Luhr (ich vermisse eine PN-Funktion): Ich klinke mich hier mal mit ein. Du schreibst weiter oben, das Du die POCOs direkt im XAML bindest. Schön und gut, war ich auch am überlegen. Allerdings verliere ich dann die Möglichkeit, z.b. die Speichern-Schaltfläche nach bestimmten Eingaben freizugeben, da ja der Setter einer POCO-property numal nicht CanSpeichern aktualisiert. Generell das PropertyChanged-Event abzufragen erscheint mir hier eher unbequem. "Lebst" Du damit oder gibt es da einen Trick?
Jens Duczmal 30.11.2011
PN geht jetzt über mein Profil.
Das mit dem Speichern-Button mussten wir leider ganz anders lösen, als ich es urspründlich wollte.
Die Anforderung war, dass ein Speichern-Button enabled wird, sobald sich ein Inhalt ändert. Das bedeutet, ich muss darauf reagieren, wenn der Kunde anfängt loszutippen. Das ist bevor überhaupt ein PropertyChanged-Event gefeuert wird.
Darauf zielte dann auch meine Frage ab: http://codekicker.de/fragen/silverlight.datagrid.events-Event-Silverlight-DataGrid-gefeuert-Inhalt-Zelle-aendert/1173
Jürgen Luhr 30.11.2011

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH