Separazione del recupero di dati e oggetti business tra i livelli DAL e BLL


9

Ho fatto delle ricerche prima di pubblicare questa domanda. Tra le altre domande o post, uno di questi è fornito di seguito. Non sono riuscito a capire bene come determinare ..

Oggetti business all'interno di un livello di accesso ai dati

Ho un repository e i livelli aziendali chiamano il repository per recuperare i dati. Ad esempio, supponiamo che io abbia le seguenti classi per BLL e 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; }
}

Se il BLL desidera recuperare un oggetto Cliente, chiamerebbe GetCustomerById (customerId) in DAL.

Di seguito sono le mie preoccupazioni che non sono riuscito a capire bene:

  1. Non riesco a vedere come determinare quale oggetto deve restituire GetCustomerById in DAL? Dovrebbe restituire BllCustomer o DalCustomer?

  2. Dove dovrebbe essere il recupero (e / o la conversione in oggetto Business) dell'indirizzo associato al cliente?

Se il DAL restituisce gli oggetti Dal, la logica per recuperare e compilare l'indirizzo può essere solo nel BLL. Se DAL restituisce oggetti BLL, la logica per recuperare e compilare l'indirizzo può essere in BLL o DAL. Attualmente il DAL sta restituendo gli oggetti business e la logica per compilarlo è nel DAL.

Da quello che ho letto, immagino non ci sia giusto o sbagliato. Dal link incluso sopra, ci sono persone che dicono in un modo e gli altri dicono nell'altro modo. Ma come faccio a determinare quale funziona meglio per il mio caso?

Qualsiasi aiuto sarebbe apprezzato.


2
La mia prima domanda sarebbe: si tratta di un'applicazione legacy? Ci sono molti frame ORM là fuori che rendono questo tipo di codice obsoleto e ti esorto a prendere in considerazione un tale framework ...
JDT

@JDT Non sono sicuro di cosa intendi, sto usando Entity Framework e ho lo stesso identico problema. A quanto ho capito, non dovresti usare il tuo ORM come oggetti di dominio, quindi dove viene fatta la traduzione?
pseudocoder,

Perché il tuo framework ORM non dovrebbe restituire anche oggetti che sono oggetti di dominio?
JDT,

3
@JDT L'ORM (EF in questo caso) restituisce classi di entità che rappresentano, in genere, una tabella di database per classe. Questo di solito è simile, ma non necessariamente uguale, alle classi di dominio. Forse stai solo dicendo che è ok usare le classi ORM come classi di dominio? Ho letto in diversi posti che questo è un no-no.
pseudocoder

Risposte:


5

Non riesco a vedere come determinare quale oggetto deve restituire GetCustomerById in DAL? Dovrebbe restituire BllCustomer o DalCustomer?

Dovrebbe restituire un oggetto DalCustomer , la restituzione di un oggetto BllCustomer infrange il principio di responsabilità singola . È possibile visualizzare l' oggetto DalCustomer come interfaccia o contratto utilizzato dal livello aziendale (o dal consumatore). In effetti, se restituisse un cliente Bll, il DAL dovrebbe soddisfare ogni oggetto del livello aziendale che lo chiama o che potrebbe potenzialmente chiamarlo.

Dove dovrebbe essere il recupero (e / o la conversione in oggetto Business) dell'indirizzo associato al cliente?

La conversione deve essere eseguita in un modello di vista o gestore. È necessario disporre di un intermediario per chiamare il servizio o il componente di accesso ai dati. Se senti il ​​bisogno, puoi avere una conversione nel tuo oggetto BllCustomer . Ma quando si scambia il DAL da MSSQL a Oracle, ad esempio, l'oggetto (o l'interfaccia) restituito deve rimanere lo stesso.

Preferibilmente, anche il livello aziendale dovrebbe essere indipendente dal livello dati. Il livello aziendale è responsabile delle regole aziendali. È qui che aggiungerai le tue validazioni usando un framework di validazione per far rispettare le tue regole di business.


4

Il repository dovrebbe restituire il BLL o l'oggetto dominio. è probabile che non ti serva affatto un oggetto DAL.

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"]);
    }
}

BLL o una libreria di classi separata dovrebbero esporre interfacce anziché classi concrete come Customer?
Yola,

1
No. Va bene esporre classi concrete. Un'interfaccia per il repository sarebbe utile
Ewan,

3

In genere, il DAL non ha alcuna conoscenza del BLL. Pensala in questo modo, un'applicazione diversa con un BLL diverso potrebbe utilizzare lo stesso DAL. Un'applicazione / modulo Debiti e un'app Crediti per la stessa società condividono i dati (clienti, addebiti, pagamenti, ecc.). Cercare di avere una DLL con conoscenza di più BLL sarebbe molto difficile e inutile. Ciò consentirebbe anche di modificare l'archiviazione dei dati senza alcun impatto sul BLL (purché non si rompano le interfacce).

È ora possibile passare un oggetto DAL al BLL oppure è possibile creare un terzo set di oggetti: Entità. Questi conterrebbero solo i valori da trasmettere insieme. Il DAL farebbe riferimento all'entità e interagire con il proprio archivio / database e il BLL gestirà tutta la logica e farebbe riferimento al DAL.

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
}

Grazie per il tuo commento. Sono d'accordo con te .. Posso già vedere che il nostro DAL / (repository) è già pieno di logiche come se il tipo sia A, quindi vai a recuperare i dati dalla tabella B, ma se il tipo è C, quindi vai a recuperare i dati dalla tabella C. Ma sono confuso con il tuo esempio usando EntCustomer. Nel mio caso, DalCustomer è il mirror delle tabelle nel DB. Puoi fornire ulteriori esempi, come viene utilizzato EntCustomer o perché dovrei usarlo e benefici di esso. Sto pensando di cambiare DAL per restituire DalObjects al BLL. Bll bloccherà la conversione in Business Objs, recupererà e compilerà l'oggetto nidificato.
ShamirDaj,

Puoi fornire più feedback?
ShamirDaj,

Penso che lo scopo degli Ent-object sia semplicemente trasferire i dati tra DAL e BLL. Le tue classi DAL possono continuare a rispecchiare la struttura db, ma quelle classi sarebbero interne a DAL. Quando il BLL richiede dati dal DAL, il DAL preleva gli oggetti DAL richiesti dal database (dalcustomer + daladdress) e costruisce da loro un'istanza di EntCustomer e li restituisce a BLL.
Artokai,

-1

DAL dovrebbe essere indipendente da BL e BL dipendente da DAL. L'interfaccia utente deve accedere ai dati solo tramite BL. È buona norma restituire DataTable o DataRow da DAL e quindi convertire DataTable / DataRow in oggetti BL. Quando l'interfaccia utente deve accedere ai dati, può accedere da BL. Quindi l'interfaccia utente sarà indipendente dal nome della colonna e dal tipo di database (SQL Server, Oracle ..). In questo modo la tua UI sarà totalmente indipendente da DAL. Personalmente preferisco il nome della classe come "CustomerBL", non usare la parola BL per chiedere il nome della classe.

Di seguito vedi Codice di esempio.

//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;
    }
}

Err ... Questo non significa che il tuo BLL deve avere conoscenza del formato / struttura delle tue tabelle di dati? ...
Paul
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.