Soll ich in einer Schichtenarchitektur, die Entity Framework verwendet, POCO-Klassen von der BLL zurückgeben? (Architektur Anleitung benötigt)

8

Ich habe wahrscheinlich zu viel gelesen und leide an Informationsüberflutung. Ich würde mich daher über eine explizite Anleitung freuen.

Nach dem, was ich gesammelt habe, kann ich VS2010's T4-Templates verwenden, um POCO-Klassen zu generieren, die nicht direkt an die EF gebunden sind. Ich würde diese in ihrem eigenen Projekt platzieren, während meine DAL eine von ObjectContext abgeleitete Klasse hätte, richtig?

Wenn ich diese Klassen habe, ist es akzeptabel, sie in der UI-Ebene zu verwenden? Das heißt, eine der generierten Klassen ist BookInfo , die Zeug über Bücher für eine öffentliche Bibliothek (Titel, Edition, Seiten, Zusammenfassung usw.) Enthält.

Meine BLL würde eine Klasse BooksBLL zum Beispiel wie folgt enthalten:

%Vor%

Meine ViewModels in meiner MVVM UI-App kommunizieren also mit der obigen BLL-Klasse und tauschen BookInfo-Instanzen aus. Ist das okay?

Darüber hinaus empfehlen MVVM-Veröffentlichungen im Internet die Implementierung von IDataErrorInfo für Validierungszwecke. Ist es in Ordnung, wenn ich diese Schnittstelle in der generierten POCO-Klasse implementiere? Ich sehe aus Beispielen, dass diese generierten POCO-Klassen alle virtuellen Eigenschaften und Stuff enthalten und ich hoffe, meine eigene Logik hinzufügen zu können, wäre okay?

Wenn es einen Unterschied macht, verwendet meine App derzeit keine WCF (oder Netzwerk-Tools).

Auch wenn Sie mit der Art und Weise, wie ich meine BLL erstelle, etwas schrecklich falsch sehen, können Sie auch in diesem Bereich Hilfe anbieten.

Update (Zusätzliche Informationen wie angefordert):

Ich versuche eine Bibliotheksautomatisierungsanwendung zu erstellen. Es basiert derzeit auf nicht Netzwerken.

Ich denke über Schichten wie folgt nach:

  • Ein Projekt, bestehend aus generierten POCO-Klassen (BookInfo, Autor, Mitglied, Verleger, Kontakt etc.)
  • Ein Projekt mit der ObjectContext-abgeleiteten Klasse (DAL?)
  • Ein Business Logic Layer mit Klassen wie dem oben erwähnten (BooksBLL, AuthorsBLL etc)
  • Ein WPF-UI-Layer, der das MVVM-Muster verwendet. (Daher meine Unterfrage zur Implementierung von IDataErrorInfo).

Ich frage mich also, ob wir eine Instanz von BooksBLL in einer ViewModel-Klasse verwenden, ResolveSearch() aufrufen, um eine List<BookInfo> zu erhalten und sie zu präsentieren ... das heißt, die POCO-Klassen überall zu verwenden.

Oder sollte ich zusätzliche Klassen haben, die die von meinem BLL offen gelegten POCO-Klassen spiegeln?

Wenn weitere Details benötigt werden, fragen Sie bitte.

    
ForeverLearnNeverMaster 12.04.2011, 15:57
quelle

3 Antworten

3

Sie brauchen nicht etwas besonders zu tun ... wie Mark sagte, es gibt keine "richtige" Antwort. Wenn Ihre Anwendung jedoch so einfach ist, dass Sie Ihre Klassen einfach duplizieren würden (z. B. BookInfoUI & amp; BookInfoBLL), würde ich Ihnen empfehlen, nur die Business-Klassen zu verwenden. Die zusätzliche Schicht würde keinen Zweck erfüllen und sollte daher nicht existieren. Eric Evans in DDD empfiehlt sogar, alle Ihre Logik in die UI-Ebene zu stellen, wenn Ihre App einfach ist und sehr wenig Geschäftslogik hat.

Um die Unterscheidung zu treffen, sollte die Anwendungsschicht über Klassen verfügen, die modellieren, was innerhalb der Anwendung geschieht, und die Domänenschicht sollte über Klassen verfügen, die modellieren, was in der Domäne geschieht. Wenn Sie beispielsweise eine Suchseite haben, ruft Ihre UI-Schicht möglicherweise eine Liste von BookSearchResult-Objekten aus einem BookSearchService in der Anwendungsebene ab, die die Domäne verwenden würde, um eine Liste von BookInfo abzurufen.

    
Misko 12.04.2011, 17:33
quelle
4

Was Sie tun, ist im Grunde das Repository-Muster, für das Entity Framework und POCO sehr gut geeignet sind.

  

Meine ViewModels in meiner MVVM UI-App kommunizieren also mit der obigen BLL-Klasse und tauschen BookInfo-Instanzen aus. Ist das okay?

Genau dafür sind POCO-Objekte da; Es gibt keinen Unterschied zwischen den generierten Klassen und wie Sie sie manuell schreiben würden. Es ist Ihr ObjectContext, der die Logik widerspiegelt, alle Änderungen in der Datenbank festzuhalten und diese nicht direkt Ihrer Benutzeroberfläche zugänglich zu machen.

Ich bin nicht persönlich mit IDataErrorInfo vertraut, aber wenn Ihre Entitäten im Moment nur in dieser einzelnen App verwendet werden, sehe ich keinen Grund, sie nicht direkt in die generierten Klassen zu schreiben. Das Hinzufügen zur T4-Vorlage wäre ideal, wenn dies möglich wäre. Dadurch würde es für eine Klasse unnötig sein, sie für jede Klasse manuell zu codieren, wenn die Fehlermeldungen einem logischen Muster folgen.

  

Auch wenn Sie mit der Art und Weise, wie ich meine BLL erstelle, etwas schrecklich falsch sehen, können Sie auch in diesem Bereich Hilfe anbieten.

Das ist nicht furchtbar falsch , aber wenn Sie Unit-Tests gegen Ihre BLL schreiben möchten (was ich empfehlen würde), sollten Sie Ihr ObjectContext -Member in% ändern. Code%. Auf diese Weise können Sie jede Klasse ersetzen, die die Schnittstelle IObjectContext zur Laufzeit implementiert (z. B. Ihre tatsächliche IObjectContext ), mit der Sie Tests für einen im Speicher befindlichen Kontext durchführen können muss nicht die Datenbank treffen.

Denken Sie auch darüber nach, Ihr ObjectContext durch ein Interface irgendeiner Art wie List<BookInfo> oder IList<BookInfo> oder den kleinsten gemeinsamen Nenner IBindingList<BookInfo> zu ersetzen. Auf diese Weise sind Sie nicht direkt an die spezifische Klasse IEnumerable<BookInfo> gebunden und wenn sich Ihre Bedürfnisse im Lauf der Zeit ändern, wird das Refactoring reduziert, das Sie benötigen, um List<T> durch etwas anderes zu ersetzen, vorausgesetzt, dass Sie ersetzen Es implementiert die von Ihnen gewählte Schnittstelle.

    
Joel C 12.04.2011 17:31
quelle
2

Antworten auf Ihre Fragen können von der Größe und Komplexität Ihrer Anwendung abhängen. Ich fürchte also, dass es gute Argumente geben wird, um Ihre Fragen mit Ja und Nein zu beantworten.

Persönlich werde ich Ihre beiden Hauptfragen beide mit Ja beantworten:

Ist es akzeptabel, POCO (Domain) -Klassen in der UI-Ebene zu verwenden?

Ich denke, mit "UI-Layer" meinen Sie nicht den View-Teil des MVVM-Patterns, sondern die ViewModels. (Die meisten MVVM-Spezialisten würden sich dagegen aussprechen, eine View direkt auf das Modell verweisen zu lassen, glaube ich.)

Es ist nicht ungewöhnlich, ein POCO aus Ihrem Domain-Projekt als Eigenschaft in ein ViewModel einzubinden und dieses umschlossene POCO direkt an die View zu binden. Das große Pro ist: Es ist einfach. Sie benötigen keine zusätzlichen ViewModel-Klassen oder replizierten Eigenschaften in einem ViewModel und kopieren dann diese Eigenschaften zwischen die Objekte.

Wenn Sie jedoch WPF verwenden, müssen Sie berücksichtigen, dass die Bindungs-Engine direkt in Ihre POCO-Eigenschaften schreibt, wenn Sie sie an eine Ansicht binden. Dies ist möglicherweise nicht immer das, was Sie möchten, insbesondere wenn Sie mit angehängten und änderungsverfolgten Entitäten in einem WPF-Formular arbeiten. Sie müssen über Stornoszenarien nachdenken oder wie Sie nach einer Stornierung Eigenschaften wiederherstellen, die von der Binding-Engine geändert wurden.

In meinem aktuellen Projekt arbeite ich mit getrennten Entitäten: Ich lade das POCO von der Datenschicht, entferne es aus dem Kontext, entsorge den Kontext und arbeite dann mit dieser Kopie im ViewModel und binde es an die View. Das Aktualisieren in der Datenschicht geschieht durch Erstellen eines neuen Kontexts, Laden der ursprünglichen Entität aus der DB nach ID und anschließendes Aktualisieren der Eigenschaften aus dem geänderten POCO, das an die Ansicht gebunden war. Das Problem der ungewollten Veränderungen einer angehängten Entität verschwindet mit diesem Ansatz. Es gibt jedoch auch Nachteile, wenn man mit abgelösten Entitäten arbeitet (Aktualisierung ist zum Beispiel komplexer).

Ist es in Ordnung, wenn ich die IDataErrorInfo -Schnittstelle für die generierte POCO-Klasse implementiere?

Wenn Sie Ihre POCO-Entitäten an eine View binden (durch ein Wrapping-ViewModel), ist es nicht nur OK, sondern Sie müssen % IDataErrorInfo in der POCO-Klasse implementieren, wenn Sie die integrierte in der Eigenschaftsprüfung der WPF-Binding-Engine. Obwohl diese Schnittstelle hauptsächlich zusammen mit UI-Technologien verwendet wird, ist sie Teil von System.ComponentModel namespace und daher nicht direkt an UI-Namespaces gebunden. Grundsätzlich ist IDataErrorInfo nur ein einfacher Vertrag, der das Melden des Objektstatus unterstützt, was auch außerhalb eines UI-Kontexts nützlich sein kann.

Das Gleiche gilt für die Schnittstelle INotifyPropertyChanged , die Sie auch in Ihren POCO-Klassen implementieren müssen, wenn Sie sie direkt an eine Ansicht binden.

Ich sehe oft Meinungen, die aus verschiedenen architektonischen Gründen nicht mit mir übereinstimmen würden. Aber keine dieser Meinungen argumentiert, dass ein anderer Ansatz einfacher ist. Wenn Sie unbedingt vermeiden möchten, POCO-Modellklassen in Ihrer ViewModel-Ebene zu verwenden, müssen Sie eine weitere Zuordnungsschicht mit zusätzlicher Komplexität sowie Programmier- und Wartungsaufwand hinzufügen. Also würde ich wählen: Halten Sie es einfach, solange Sie keinen überzeugenden Grund und klaren Nutzen haben, um Ihre Architektur komplexer zu machen.

    
Slauma 12.04.2011 17:36
quelle