Trennung des Abrufs von Daten und Geschäftsobjekten zwischen DAL- und BLL-Ebenen

9

Ich habe einige Nachforschungen angestellt, bevor ich diese Frage gestellt habe. Eine der folgenden Fragen oder Beiträge ist unten aufgeführt. Ich konnte mir nicht klar machen, wie ich bestimmen soll.

Geschäftsobjekte innerhalb einer Datenzugriffsschicht

Ich habe ein Repository und die Business Layer rufen das Repository auf, um die Daten abzurufen. Angenommen, ich habe die folgenden Klassen für BLL und DAL:

class BllCustomer
{
    public int CustomerId {get; set;}
    public String Name {get; set;}
    public BllAddress Address {get; set;}
}

class BllAddress
{
     public int AddressId {get; set;}
     public String Street {get; set;}
     public String City {get; set;}
     public String ZipCode {get; set; }
}

class DalCustomer 
{
    public int CustomerId {get; set;}
    public String Name {get; set;}
    public int AddressID {get; set;}
}

class DalAddress
{
     public int AddressId {get; set;}
     public String Street {get; set;}
     public String City {get; set;}
     public String ZipCode {get; set; }
}

Wenn die BLL ein Kundenobjekt abrufen möchte, ruft sie GetCustomerById (customerId) in DAL auf.

Folgendes sind meine Bedenken, die ich nicht klarstellen konnte:

  1. Ich kann nicht sehen, wie bestimmt werden soll, welches Objekt die GetCustomerById in DAL zurückgeben soll. Sollte es BllCustomer oder DalCustomer zurückgeben?

  2. Wo soll die mit dem Kunden verknüpfte Adresse abgerufen (und / oder in ein Geschäftsobjekt konvertiert) werden?

Wenn der DAL Dal-Objekte zurückgibt, kann sich die Logik zum Abrufen und Ausfüllen der Adresse nur in der BLL befinden. Wenn die DAL BLL-Objekte zurückgibt, kann die Logik zum Abrufen und Ausfüllen der Adresse entweder in der BLL oder in der DAL liegen. Derzeit gibt die DAL die Geschäftsobjekte zurück und die Logik zum Ausfüllen befindet sich in der DAL.

Nach dem, was ich gelesen habe, gibt es wohl kein Richtig oder Falsch. Über den oben angegebenen Link sagen Leute den einen und die anderen den anderen Weg. Aber wie bestimme ich, welches für meinen Fall am besten geeignet ist?

Jede Hilfe wäre dankbar.

ShamirDaj
quelle
2
Meine erste Frage wäre: Ist dies eine Legacy-Anwendung? Es gibt viele ORM-Frameworks, die diese Art von Code überflüssig machen, und ich möchte Sie dringend bitten, ein solches Framework in Betracht zu ziehen ...
JDT
@JDT Ich bin mir nicht sicher, was du meinst. Ich verwende Entity Framework und habe genau das gleiche Problem. Soweit ich weiß, sollten Sie Ihr ORM nicht als Domänenobjekte verwenden. Wo wird also die Übersetzung vorgenommen?
Pseudocoder
Warum sollte Ihr ORM-Framework keine Objekte zurückgeben, die ebenfalls Domänenobjekte sind?
JDT
3
@JDT Das ORM (in diesem Fall EF) gibt Entitätsklassen zurück, die normalerweise eine Datenbanktabelle pro Klasse darstellen. Dies ähnelt normalerweise den Domänenklassen, ist jedoch nicht unbedingt mit diesen identisch. Vielleicht sagen Sie nur, dass es in Ordnung ist, ORM-Klassen als Domänenklassen zu verwenden? Ich habe an mehreren Stellen gelesen, dass dies ein Nein-Nein ist.
Pseudocoder

Antworten:

5

Ich kann nicht sehen, wie bestimmt werden soll, welches Objekt die GetCustomerById in DAL zurückgeben soll. Sollte es BllCustomer oder DalCustomer zurückgeben?

Es sollte ein DalCustomer- Objekt zurückgeben. Wenn Sie ein BllCustomer- Objekt zurückgeben, wird das Prinzip der Einzelverantwortung verletzt . Sie können das DalCustomer- Objekt als Schnittstelle oder Vertrag anzeigen, die von der Geschäftsschicht (oder dem Verbraucher) verwendet werden. Wenn ein BllCustomer zurückgegeben würde, müsste der DAL für jedes Business-Layer-Objekt sorgen, das ihn aufruft oder möglicherweise aufrufen könnte.

Wo soll die mit dem Kunden verknüpfte Adresse abgerufen (und / oder in ein Geschäftsobjekt konvertiert) werden?

Die Konvertierung sollte in einem Ansichtsmodell oder Manager erfolgen. Sie benötigen einen Vermittler, um Ihre Dienst- oder Datenzugriffskomponente aufzurufen. Wenn Sie dies benötigen, können Sie eine Konvertierung in Ihrem BllCustomer- Objekt vornehmen . Wenn Sie dann beispielsweise Ihre DAL von MSSQL auf Oracle umstellen, muss Ihr zurückgegebenes Objekt (oder Ihre zurückgegebene Schnittstelle) gleich bleiben.

Vorzugsweise sollte Ihre Geschäftsschicht auch unabhängig von Ihrer Datenschicht sein. Die Geschäftsschicht ist für Ihre Geschäftsregeln verantwortlich. Hier fügen Sie Ihre Validierungen mithilfe eines Validierungsframeworks hinzu, um Ihre Geschäftsregeln durchzusetzen.

Derika
quelle
4

Ihr Repository sollte die BLL oder das Domänenobjekt zurückgeben. Möglicherweise benötigen Sie überhaupt kein DAL-Objekt.

public class Customer
{
    public string Name {get; private set;}
    public Customer(string name)
    {
        this.Name = name;
    }
}

public class Repository
{
    public Customer GetCustomer(string id)
    {
        //get data from db
        return new Customer(datarow["name"]);
    }
}
Ewan
quelle
Sollte BLL oder eine separate Klassenbibliothek Schnittstellen anstelle konkreter Klassen wie Customerverfügbar machen?
Yola
1
Nein, es ist in Ordnung, konkrete Klassen aufzudecken. Eine Schnittstelle für das Repository wäre nützlich
Ewan
3

In der Regel kennt der DAL die BLL nicht. Stellen Sie sich das so vor, eine andere Anwendung mit einer anderen BLL könnte dieselbe DAL verwenden. Eine Anwendung / ein Modul für Verbindlichkeiten und eine App für Forderungen für dasselbe Unternehmen würden Daten (Kunden, Gebühren, Zahlungen usw.) gemeinsam nutzen. Der Versuch, eine DLL über Kenntnisse über mehr als eine BLL zu verfügen, wäre sehr schwierig und unnötig. Auf diese Weise können Sie auch Ihren Datenspeicher ändern, ohne dass dies Auswirkungen auf die BLL hat (solange Sie die Schnittstellen nicht beschädigen).

Sie können jetzt ein DAL-Objekt an die BLL übergeben oder einen dritten Satz von Objekten erstellen: Entität. Diese würden nur die Werte enthalten, die zusammen weitergegeben werden sollen. Die DAL würde auf die Entität verweisen und mit Ihrem Speicher / Ihrer Datenbank interagieren, und die BLL würde die gesamte Logik verarbeiten und auf die DAL verweisen.

class EntCustomer
{
    public int CustomerId {get; set;}
    public String Name {get; set;}
    public BllAddress Address {get; set;}
}
class BllCustomer
{
   //reference EntCustomer, DalCustomer and handle business rules/logic
}

class DalCustomer 
{
   //reference EntCustomer and interact with data storage
}
JeffO
quelle
Danke für deinen Kommentar. Ich stimme Ihnen zu. Ich kann bereits sehen, dass unser DAL / (Repository) bereits mit Logiken gefüllt ist, z. B. wenn der Typ A ist. Rufen Sie dann Daten aus Tabelle B ab. Wenn der Typ jedoch C ist, rufen Sie Daten aus Tabelle ab C. Aber ich bin verwirrt mit Ihrem Beispiel mit EntCustomer. In meinem Fall ist DalCustomer ein Spiegel der Tabellen in DB. Können Sie weitere Beispiele nennen, wie der EntCustomer verwendet wird oder warum ich ihn verwenden sollte und welche Vorteile er hat? Ich denke darüber nach, DAL zu ändern, um DalObjects an die BLL zurückzugeben. Bll wird die Konvertierung in Geschäftsobjekte hängen, verschachtelte Objekte abrufen und ausfüllen.
ShamirDaj
Können Sie mehr Feedback geben?
ShamirDaj
Ich denke, dass der Zweck der Ent-Objekte darin besteht, nur Daten zwischen DAL und BLL zu übertragen. Ihre DAL-Klassen können weiterhin die Datenbankstruktur spiegeln, diese Klassen sind jedoch DAL-intern. Wenn die BLL Daten von DAL anfordert, ruft die DAL die erforderlichen DAL-Objekte aus der Datenbank ab (dalcustomer + daladdress) und erstellt daraus eine Instanz von EntCustomer und gibt sie an BLL zurück.
Artokai
-1

DAL sollte unabhängig von BL und BL sein und von DAL abhängen. Ihre Benutzeroberfläche sollte nur über BL auf Daten zugreifen. Es empfiehlt sich, wenn Sie DataTable oder DataRow von DAL zurückgeben und dann DataTable / DataRow in BL-Objekte konvertieren. Wenn Ihre Benutzeroberfläche auf die Daten zugreifen muss, kann sie von BL aus zugreifen. Die Benutzeroberfläche ist also unabhängig vom Spaltennamen und vom Datenbanktyp (SQL Server, Oracle ..). Auf diese Weise ist Ihre Benutzeroberfläche völlig unabhängig von DAL. Persönlich bevorzuge ich Klassennamen wie "CustomerBL". Verwenden Sie das BL-Wort nicht zum Bitten um Klassennamen.

Unten siehe Beispielcode.

//Customer Class
class BllCustomer
{
    public int CustomerId { get; set; }
    public String Name { get; set; }
    public BllAddress Address { get; set; }

    public static BllCustomer GetByCustomerId(int id)
    {
        DataRow dr = DalCustomer.GetByCustomerId(id);
        if (dr == null)
            return null;
        BllCustomer oCust = new BllCustomer();
        oCust.CustomerId = int.Parse(dr["CustomerId"].ToString());
        //Do for other class members and load values

        return oCust;
    }
}


class DalCustomer
{

    public static DataRow GetByCustomerId(int id)
    {
        //Get Data row from Database and return Datarow
        DataRow CustomerRow = GETFROMDATABASE("SELECT * from CUSTOMER");
        return CustomerRow;
    }
}
Jigneshk
quelle
Äh ... Bedeutet das dann nicht, dass Ihre BLL Kenntnisse über das Format / die Struktur Ihrer Datentabellen haben muss? ...
Paul