2013-04-02 20 views
7

Ich möchte eine Webanwendung mit 3-Tier-Architektur in ASP.NET erstellen. Aber ich bekomme ein Problem der Zirkelreferenzierung.Circular Referenz Problem in 3-Tier-Architektur C#

Ich habe 3-Schicht:

  1. Anwendungsschicht, die UI.
  2. Business-Schicht, die alle Logik- und Domänenklassen enthält.
  3. Datenschicht, die alle Datenbankinteraktionsmethoden enthält.

Ich bin mit der Datenschicht Methoden in Business-Schicht Datenbankoperationen durchzuführen und in diesen Methoden muß ich Domain-Klasse-Objekt Datenschicht passieren, aber es kann nicht aufgrund von Kreis Referenzierung erfolgen.

Zum Beispiel habe ich eine Person Domain-Klasse mit einigen Eigenschaften und Methoden. Jetzt möchte ich das Person in die Datenbank einfügen. Ich habe eine Methode in der Klasse Person namens InsertPerson(). In diesem Methodenkörper muss ich die Funktion der Datenschicht aufrufen, um sie in die Datenbank einzufügen. Aber ich bin nicht in der Lage, das gesamte Personenobjekt in die Datenschichtmethode zu übertragen, da die Datenebenenreferenz zu der Geschäftsschicht hinzugefügt wird und umgekehrt nicht möglich ist.

Also, wie kann ich dieses Problem vermeiden? Bitte vorschlagen.

+0

Wie ich es getan gesehen habe 1. Es gibt eine Basisklasse aller Geschäftsobjekten Jets, von denen sowohl die Unternehmens- als auch die Datenschicht Kenntnis haben. Es kennt seine Tabelle und ist einer Zeile zugeordnet. 2. Um zu speichern, muss die Datenschicht nur ihre Zeile nehmen, ihr Schema untersuchen, die Abfrage konstruieren, um sie zu speichern, und sie in dieser Tabelle speichern. 3. Zum Laden wird dem Datenlayer ein Typ übergeben, der BusinessObjects als Unterklassen verwendet, und reflektiv den Konstruktor des Typs in der Zeile verwendet, die er aus der Tabelle bezieht. – Patashu

+0

Ich fügte meiner Antwort eine Bearbeitung hinzu, um klarer zu beschreiben, was ich meinte. –

Antwort

8

Ist es möglich, die Domänenobjekte von der Geschäftslogik zu trennen, um sie zu manipulieren? So haben Sie Klassen beschreiben die Daten, die relativ primitive Operationen enthält, und dann Ihre Business-Schicht ist mehr Aktionen auf die Daten - oft mit mehreren verschiedenen Klassen in einer Aktion.

Sie dann vier Baugruppen am Ende mit:

UI   /
    Business logic | Domain classes 
    Data layer  \ 

So alle drei Schichten, die die Domain-Klassen als gemeinsame Terminologie verwenden, effektiv.

Ich habe diese Arbeit ziemlich gut gesehen - es bedeutet, dass Ihre Domain-Klassen typischerweise etwas „dumm“ worden, obwohl sie nach wie vor relevant Logik um einig Validierung etc. für Aspekte enthalten können, die von anderen Klassen unabhängig sind.

Natürlich gibt es viele alternative Ansätze :)

+0

Wie sieht die SavePerson-Methode in der Datenzugriffsebene in dieser Lösung aus? –

+0

@Peri: Es ist schwierig, das ohne weitere Informationen zu beantworten - aber ich würde erwarten, dass die Datenschicht keine Geschäftslogik enthält - nur wissen, wo und wie die Entitäten gespeichert wurden. Was genau das bedeutet, hängt von vielen anderen Kontexten ab. (Ich habe zu lange an ziemlich proprietären Lösungen gearbeitet, um dies generell zu kommentieren.) –

+0

Ich sollte klarer sein. Ich wollte fragen, ob DataAccess.SavePerson Person als Parameter oder Vorname, Nachname empfängt. Ich verstehe nicht, wie Referenzen zwischen den Versammlungen organisiert sind. –

-1

Wenn Sie in Ihrer Anwendung eine 3-Tier-Architektur verwenden, können Sie kein Objekt an die Datenzugriffsebene übergeben. Die Objekte können nur in der Business-Schicht verwendet werden. Die beste Architektur ist das Domänenmodul, wenn Sie ein Objekt in der Datenzugriffsebene verwenden möchten.

1

Sie würden besser verwenden klassische DDD: Domain (Business-Logik) sollten keinen Hinweis auf DAL haben (Infrastruktur für die Persistenz) erklärt sie nur Schnittstellen dass die Infrastruktur muss (Repositories) implementieren als in der Anwendungsschicht schreiben Sie App Dienstleistungen, die Domain und die Präsentationsschicht verwenden verwendet nur Anwendungsschicht (oder verteilte Dienste, wenn es geht um verteilte app):

enter image description here

Gutes Beispiel für (D) DDD: http://microsoftnlayerapp.codeplex.com/

+1

Ich denke, du solltest lesen, was Ayende Rahien über den Code sagt, den du verlinkt hast. –

+0

gibt es nichts DDD spezifisch in dieser Lösung. –

3

Ihre Geschäftslogik-DLL sollte keinen Bezug zur Datenzugriffsebene haben. Die Datenzugriffsebene sollte einen Verweis auf Ihre Geschäftslogik-DLL haben. Geschäftslogik-Code sollte Schnittstellen definieren, mit denen er kommunizieren möchte, um auf die Datenbank (oder andere externe Geschäftslogikdaten) zuzugreifen, und andere DLLs sollten sie implementieren, um Dienste für die Geschäftslogikebene bereitzustellen.

Dies ist das Dependency Inversion-Prinzip. Es besagt, dass High-Level-Module nicht von Low-Level-Modulen abhängen sollten. Hier ist Business-Logik das High-Level-Modul. Datenzugriffsdll ist nur Implementierungsdetail aus Business-Logik-DLL-Perspektive.

Zum Beispiel

BLL zeigen:

 
public interface IPersonRepository 
{ 
    void SavePerson(Person p); 
} 
public class PersonServices 
{ 
    PersonServices(IPersonRepository repo) 
    { 
     // 
    } 
    public void FirePerson(Person toFire) 
    { 
     toFire.FireHim(); 
     repo.SavePerson(toFire); 
    } 
} 

DAL:

 
public class PersonRepository : IPersonRepository 
{ 
    // ... 
} 
UI:
 
var repo = new PersonRepository(); 
var ps = new PersonService(repo); // wire by hand or use container

ps.FirePerson(somePerson);

Referenzen:

 
UI -> BLL 
    -> DAL 

DAL -> BLL 

BLL -> nothing!