2009-04-06 19 views
10

ich zur Zeit eine Anwendung, die besteht aus: User Interface (Web-Seite) BLL (-Manager & Domain Objects) DAL (Data Access-Klasse für jede meiner Domain Objects).Was von der DAL nach BLL zurückzukehren

Ich verwende Folgendes in der Benutzeroberfläche, um nach einem Domänenobjekt zu suchen.

protect sub Button1_Click() 
{ 
    IBook book = BookManager.GetBook(txtID.Text); 
} 

Hier ist meine BLL

public class BookManager 
{ 
    public static IBook GetBook(string bookId) 
    { 
     return BookDB.GetBook(bookId); 
    } 
} 

public class Book : IBook 
{ 
    private int? _id 
    private string _name; 
    private string _genre; 

    public string Name 
    { 
     get { return _name; } 
     private set 
     { 
      if (string.IsNullOrEmpty(value)) 
       throw new Exception("Invalid Name"); 
      _name = value; 
     } 
    } 

    public string Genre 
    { 
     get { return _serial; } 
     private set 
     { 
      if (string.IsNullOrEmpty(value)) 
       throw new Exception("Invalid Genre"); 
      _genre = value; 
     } 
    } 

    // Other IBook Implementations 

} 

Und schließlich ist hier meine DAL

public class BookDB 
{ 
    public static IBook GetBook(int id) 
    { 
     // Get Book from database using sproc (not allowed to use any ORM) 
     // ?? Create IBook Item? 
     // return IBook 
    } 

Wie würde man einen IBook Objekt erstellen und es an den Manager zurückkehren? Ich denke darüber nach, eine DataTable von BookDB an BookManager zurückzugeben und das Book-Objekt zu erstellen und es zurückzugeben, aber das scheint nicht richtig zu sein. Gibt es einen anderen Weg, dies zu tun?

Edit: Ich entschied mich, jede Schicht in ein Projekt zu trennen und stieß auf ein zirkuläres Abhängigkeitsproblem in der DAL-Schicht, wenn versucht wurde, einen Verweis auf die BLL hinzuzufügen. Ich kann nicht auf die Buchklasse oder Schnittstelle oder irgendetwas in BLL von DAL zugreifen. Soll ich hier einfach ado.net-Objekte verwenden und muss mein Manager das eigentliche Objekt aus dem ado.net-Objekt erstellen? Hier ist, wie seine legte aus

BLL.Managers - BookManager 
BLL.Interfaces IBook 
BLL.Domain - Book 
DAL - BookDB. 

Dank!

+0

Normalerweise sollte die DAL keinen Bezug zur BLL haben. Die BLL sollte jedoch einen Verweis auf die DAL enthalten. – Martin

+0

Wenn ich ein Model Project hinzufügen würde, sollte ich dann sowohl die Dummy-Klassen als auch die Domain-Klassen/Interfaces zu diesem Projekt bewegen? – AlteredConcept

Antwort

0

Die DataTable, die Sie zurückgeben möchten, ist datenbankbezogen, und für BLL sollte es nicht wichtig sein, welche Datenbank Sie verwenden und was das Schema ist. Sie können einen DB-Object Mapper verwenden, um die dbtable einem Objekt in DAL zuzuordnen.

+0

DataTable ist nicht ganz datenbankbezogen. Sie ist spezifisch für das relationale Modell, stellt jedoch eine speicherinterne, nicht verbundene "Tabelle" dar und ist nicht mit einer Datenbank verbunden. Es gibt auch keine Informationen über eine Datenbank, die es möglicherweise gefüllt haben. –

0

Wenn Sie keine DataTable zurückgeben möchten, können Sie eine IBook-Implementierung aus BookManager übergeben, damit die DAL gefüllt wird.

5

Sie könnten Dummy-Buchobjekte erstellen, die nur Daten enthalten. Abrufen, Eigenschaften und Mitgliedswerte festlegen Dieses Buch enthält 1 Eigenschaft für jedes Feld in der Datenbank, validiert jedoch nichts.

Sie füllen das Objekt aus der Datenbank und senden es an die BLL.

Wenn Sie das Objekt speichern möchten, senden Sie es auch an die BLL.

Ihre Klassen in der BLL können diese Objekte umschließen, wenn dies sinnvoll ist. Auf diese Weise ist es einfach, es einfach an die DAL zurückzusenden.

Dummy Buch:

public class DummyBook:IBook 
{ 
    private nullable<int> _id; 
    private string _name; 
    private string _genre; 

    public string Id 
    { 
     get {return _id;} 
     set {_id = value;} 
    } 

    public string Name 
    { 
     get {return _name;} 
     set {_name = value;} 
    } 

    public string Genre 
    { 
     get {return _genre;} 
     set {_genre= value;} 
    } 

} 

DAL Buch:

public class DALBook 
{ 
    public static IBook:GetBook(int id) 
    { 
     DataTable dt; 
     DummyBook db = new DummyBook(); 

     // Code to get datatable from database 
     // ... 
     // 

     db.Id = (int)dt.Rows[0]["id"]; 
     db.Name = (string)dt.Rows[0]["name"]; 
     db.Genre = (string)dt.Rows[0]["genre"]; 

     return db; 
    } 

    public static void SaveBook(IBook book) 
    { 
     // Code to save the book in the database 
     // you can use the properties from the dummy book 
     // to send parameters to your stored proc. 
    } 
} 

BLL Buch:

public class Book : IBook 
{ 
    private DummyBook _book; 

    public Book(int id) 
    { 
     _book = DALBook.GetBook(id); 
    } 

    public string Name 
    { 
     get {return _book.Name;} 
     set 
     { 
      if (string.IsNullOrEmpty(value)) 
      { 
       throw new Exception("Invalid Name"); 
      } 
      _book.Name = value; 
     } 
    } 

    // Code for other Properties ... 



    public void Save() 
    { 
     // Add validation if required 
     DALBook.Save(_book); 
    } 

} 

Edit1: Die Dummy-Klassen in ihrem eigenen Projekt gehen (Modell, genau wie in den Kommentaren angegeben ist in Ordnung).Die Referenzen würden wie folgt funktionieren:

Die DAL verweist auf das Modellprojekt.
Die BLL verweist auf das Modell und die DAL.
Die Benutzeroberfläche verweist auf die BLL.

+0

Auf welcher Ebene würden Sie das DummyBook platzieren? Im Moment habe ich drei Projekte. 1) Web-Projekt (Enthält Verweis auf BLL) 2) BLL-Klassenbibliothek (enthält Verweis auf DAL) 3) DAL-Klassenbibliothek (enthält Verweis auf BLL) – AlteredConcept

+0

@AlteredConcept: Sie kann ein anderes Modell Projekt oder solche – smoothdeveloper

1

Ich würde wahrscheinlich ExecuteReader verwenden, um ein Objekt in Code aus der Datenbank zu erstellen. Der Grund dafür ist, dass die Datentabelle mehr Overhead als ein Leser hat, weil sie mehr Funktionalität hat (und wahrscheinlich von einem Leser erstellt wurde). Da Sie keine Aktualisierungen/Löschungen mit der Datentabelle durchführen, benötigen Sie keinen Overhead.

Das gesagt, würde ich eine statische Hilfsmethode in der BookManager-Klasse machen.

Der Grund dafür ist, dass Sie eine Schnittstelle haben, weil Sie die Implementierung möglicherweise ändern möchten. Eventuell müssen Sie INovel: IBook, IReference: IBook usw. haben und dann möchten Sie eine abstrakte Factory-Implementierung in Ihrer Datenebene haben.

public static IBook GetBook(int id) 
{ 
    // SqlCommand Command = new Command("SQL or sproc", ValidConnection); 

    using(IDataReader DR = Command.ExecuteReader(id)) 
    { 
     // checking omitted 
     switch(DR.GetInt32(1)) 
     { 
      case 0: 
       return BookManager.BookFromReader(DR); 
      case 1: 
       return BookManager.NovelFromReader(DR); 
      etc 
     } 
    } 
} 

Ein weiterer Vorteil der DAL ist, dass Sie Lookups cachen können. Sie können ein Dictionary verwenden, das Bücher enthält, nach denen Sie gesucht haben, um zusätzliche DB-Aufrufe von Objekten zu reduzieren, die Sie bereits zurückgegeben haben. Wenn ein Update stattfindet, entfernen Sie die zwischengespeicherte Entität ... Das ist jedoch ein weiterer Beitrag.

Wenn Sie mehrere Assemblys verwenden, müssen sich Schnittstellen und Hilfsmethoden in einer neutralen (nicht abhängigen) Assembly befinden. Gerade jetzt im Blog-o-Bereich, gibt es Bewegung in Richtung weniger Baugruppen, die weniger Abhängigkeiten bedeuten usw.

Hier ist ein Link von einem Blog ich zu diesem Thema lesen: http://codebetter.com/blogs/patricksmacchia/archive/2008/12/08/advices-on-partitioning-code-through-net-assemblies.aspx

Letztlich I Die Antwort lautet, dass die Datenschicht eine Instanz Ihrer Schnittstelle an die Business-Schicht zurückgibt.

Viel Glück :-)

+0

Dank ben erstellen . Das hilft. Aus irgendeinem seltsamen Grund dachte ich, dass es seit BookManager Calls BookDB.GetBook, es ein bisschen komisch erscheint, es innerhalb der BookDB.GetBook Methode von innen aufzurufen. Ich weiß nicht, warum ich das gedacht habe. Danke nochmal! – AlteredConcept

+0

Sie könnten die statische Hilfsmethode in die DAL oder BLL einfügen. Ich vermute, dass ich wegen der Platzierung in der BLL geflammt werde. Ich wähle die BLL, weil die DAL "ausgetauscht" werden konnte, während die Hilfsmethoden immer noch angewendet wurden ... –

+0

Ich dachte, ich hätte die Antwort hier, ich bin überrascht, die -1 zu sehen. Würde die -1 bitte per Kommentar ausarbeiten? –

2

BookDB sollte die IBook Instanz zurück. Ich mag das Repository-Muster, bei dem es um die Zuordnung von der Datenbank zur Domäne geht.

Die Repository-Implementierung gibt Instanzen der Domänenobjekte zurück. Dies schützt den Rest des Codes vor der bestimmten Persistenzimplementierung, die von der Technologie (Datenbanktyp, Webdienst, [etwas anderes einfügen]) und dem Format zum Speichern der Daten betroffen sein kann.

+0

Wie würden Sie das obige strukturieren, um das Repository-Muster ohne ein ORM zu verwenden? – AlteredConcept

1

Meiner Meinung nach sollten Sie DAL niemals auf BLL zugreifen lassen. Das ist eine unnötige Abhängigkeit.

Wenn Sie die Book-Klasse in ein neues Projekt einfügen (möglicherweise DomainModel genannt), wird der Zirkelverweis korrigiert. Man könnte so etwas tun:

Projekt BLL Referenz DAL und DomainModel

Projekt DAL Referenz DomainModel

Projekt UI Referenz BLL und DomainModel

Projekt DomainModel Referenz nichts

0

folgen Sie den beabsichtigtes Modell. Der Data Access Layer (DAL) ist verantwortlich für das Abrufen und Senden von Daten von und zu der Datenquelle.

Die DAL muss sich nicht um eine der Geschäftsentitäten kümmern, die Ihre BLL verwendet, da ihre einzige Aufgabe darin besteht, Daten abzurufen und in einem neutralen Objekt zurückzugeben. Es muss neutral für generische Wiederverwendbarkeit sein, andernfalls könnten Sie die Schichten genauso gut nicht trennen, wie Sie ihren Zweck rechtfertigen.

Ihrem Business Logic Layer (BLL) ist es egal, wie die DAL das Abrufen oder Schreiben von Daten erreicht.

Um zwischen der BLL und der DAL zu kommunizieren, müssen Sie neutrale Objekte verwenden.

Ihr BLL übergibt die Eigenschaften eines Objekts als einzelne Parameter an die Methoden in der DAL. Die Parameter in der DAL sind neutral mit strings, int, bool, anderen .NET-Objekten, die weder spezifisch für eine Version der Datenbank sind, mit der Sie kommunizieren, noch sind bestimmte Typen nur in Ihrer BLL vorhanden.

Die DAL wird die Daten von wo immer je nach Bedarf abrufen und ein neutrales Datenobjekt an den Aufrufer zurückgeben. Dies könnte beispielsweise ein DataSet oder DataTable oder ein anderes Objekt sein, das NICHT für einen von Ihnen verwendeten Datenbanktyp/-version spezifisch ist. Daher sind DataSet und DataTable Objekte im System.Data-Namespace und nicht im Namespace System.Data.SQL, etc ....

Im Wesentlichen: - BLL geht neutrale Typen zum DAL (zB: string, int, bool, long, float, etc ..) - DAL ist verantwortlich für diese Typen Datenbank specifci-Typen konvertiert werden, falls erforderlich, bevor er sie auf die Datenquelle DAL liefert neutrale Datentypen an die BLL (zB: DataSet, DataTable, etc ..) - BLL ist verantwortlich für die Verwendung der Inhalt dieser neutralen Datentypen zu erstellen, füllen und geben Sie spezifische Business Entities

Ihr BLL muss auf Ihre DAL verweisen. das ist es.

Sie können natürlich dieses Modell vollständig ignorieren und so viele wie zuvor mit IBOOK vorgeschlagen hacken ... aber als Sie nicht das beabsichtigte Modell verwenden und könnte alles in eine einzelne Baugruppe werfen, wie Sie gewonnen haben ' t es in der Lage sein, es unabhängig zu halten.

+0

Ich zitiere Wiki hier: "[Die Daten] Tier hält Daten neutral und unabhängig von Anwendungsservern oder Geschäftslogik." Den "dummen" DAL Business Objects zu geben, steht dem nicht im Wege. Solange sich Ihre Geschäftsobjekte nicht selbst validieren und nur ein Speicher für grundlegende Datentypen sind, die in einer Klasse eingeschlossen sind, ist es besser, sie zu verwenden. Sie erhalten nichts, wenn Sie Employee_DAL.Save (myEmployee.Id, myEmployee.Name, myEmployee.JobTitle) und Employee_DAL.Save (myEmployee) ausführen. Die zweite ist viel sauberer. – colithium