Séparation de la récupération des données et des objets métier entre les couches DAL et BLL


9

J'ai fait quelques recherches avant de poster cette question. Parmi d'autres questions ou messages, l'une d'entre elles est fournie ci-dessous. Je ne pouvais pas savoir clairement comment déterminer ..

Objets métier dans une couche d'accès aux données

J'ai un référentiel et les couches métier appellent le référentiel pour récupérer les données. Par exemple, disons que j'ai les classes suivantes pour BLL et 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; }
}

Si le BLL veut récupérer un objet Customer, il appellera GetCustomerById (customerId) dans DAL.

Voici mes préoccupations, je ne pouvais pas avoir un esprit clair:

  1. Je ne vois pas comment déterminer quel objet le GetCustomerById dans DAL doit retourner? Doit-il renvoyer BllCustomer ou DalCustomer?

  2. Où devrait être la récupération (et / ou la conversion en objet métier) de l'adresse associée au client?

Si le DAL renvoie des objets Dal alors, la logique pour récupérer et remplir l'adresse ne peut être que dans le BLL. Si le DAL renvoie des objets BLL, alors la logique pour récupérer et remplir l'adresse peut être soit dans le BLL soit dans le DAL. Actuellement, le DAL renvoie les objets métier et la logique pour le remplir se trouve dans le DAL.

D'après ce que j'ai lu, je suppose qu'il n'y a pas de bien ou de mal. Du lien inclus ci-dessus, il y a des gens qui disent dans un sens et les autres disent dans l'autre sens. Mais comment puis-je déterminer ce qui fonctionnerait le mieux pour mon cas?

Toute aide serait appréciée.


2
Ma première question serait: est-ce une ancienne application? Il existe de nombreux cadres ORM qui rendent ce type de code obsolète et je vous exhorte à envisager un tel cadre ...
JDT

@JDT Je ne sais pas ce que vous voulez dire, j'utilise Entity Framework et j'ai exactement le même problème. Si je comprends bien, vous n'êtes pas censé utiliser votre ORM comme objets de domaine, alors où est la traduction?
pseudocoder

Pourquoi votre infrastructure ORM ne retournerait-elle pas également des objets qui sont des objets de domaine?
JDT

3
@JDT L'ORM (EF dans ce cas) renvoie des classes d'entité qui représentent, généralement, une table de base de données par classe. Ceci est généralement similaire, mais pas nécessairement identique aux classes de domaine. Peut-être que vous dites simplement qu'il est correct d'utiliser des classes ORM comme classes de domaine? J'ai lu à plusieurs endroits que c'est un non-non.
pseudocoder

Réponses:


5

Je ne vois pas comment déterminer quel objet le GetCustomerById dans DAL doit retourner? Doit-il renvoyer BllCustomer ou DalCustomer?

Il doit renvoyer un objet DalCustomer , le retour d'un objet BllCustomer rompra le principe de responsabilité unique . Vous pouvez afficher l' objet DalCustomer en tant qu'interface ou contrat consommé par la couche métier (ou consommateur). En effet, s'il renvoyait un BllCustomer, le DAL devrait répondre à chaque objet de couche métier qui l'appelle ou pourrait l'appeler.

Où devrait être la récupération (et / ou la conversion en objet métier) de l'adresse associée au client?

La conversion doit être effectuée dans un modèle de vue ou un gestionnaire. Vous devez avoir un intermédiaire pour appeler votre service ou composant d'accès aux données. Si vous en ressentez le besoin, vous pouvez avoir une conversion dans votre objet BllCustomer . Mais lorsque vous échangez votre DAL de MSSQL vers Oracle par exemple, votre objet (ou interface) retourné doit rester le même.

De préférence, votre couche métier doit également être indépendante de votre couche de données. La couche métier est responsable de vos règles métier. C'est ici que vous ajouterez vos validations à l'aide d'un cadre de validation pour appliquer vos règles métier.


4

Votre référentiel doit renvoyer l'objet BLL ou domaine. il est probable que vous n'ayez pas du tout besoin d'un objet 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 ou bibliothèque doit - classe séparée exposer les interfaces des classes au lieu de béton comme Customer?
Yola

1
Non, c'est bien d'exposer des classes de béton. Une interface pour le référentiel serait utile
Ewan

3

En règle générale, le DAL n'a aucune connaissance du BLL. Pensez-y de cette façon, une application différente avec un BLL différent pourrait utiliser le même DAL. Une application / module Payables et une application Receivables pour la même entreprise partageraient des données (clients, frais, paiements, etc.). Essayer d'avoir une DLL ayant connaissance de plusieurs BLL serait très difficile et inutile. Cela vous permettrait également de modifier votre stockage de données sans impact sur le BLL (tant que vous ne rompez pas les interfaces).

Vous pouvez maintenant passer un objet DAL au BLL ou vous pouvez créer un troisième ensemble d'objets: Entité. Celles-ci ne contiendraient que les valeurs à transmettre ensemble. Le DAL ferait référence à l'entité et interagirait avec votre stockage / base de données et le BLL gérerait toute la logique et référencerait le 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
}

Merci pour votre commentaire. Je suis d'accord avec vous .. Je peux déjà voir que notre DAL / (Repository) est déjà rempli de logiques comme si le type est A, alors allez récupérer les données du tableau B, mais si le type est C, alors allez récupérer les données du tableau C. Mais je suis confus avec votre exemple en utilisant EntCustomer. Dans mon cas, DalCustomer est le miroir des tables dans DB. Pouvez-vous fournir plus d'exemples, comment l'EntCustomer est utilisé ou pourquoi je devrais l'utiliser et les avantages de celui-ci. Je pense à changer DAL pour retourner DalObjects au BLL. Bll suspendra la conversion en Business Objs, récupérera et remplira l'obj imbriqué.
ShamirDaj

Pouvez-vous fournir plus de commentaires?
ShamirDaj

Je pense que le but des Ent-objets est de simplement transférer des données entre DAL et BLL. Vos classes DAL peuvent continuer à refléter la structure db, mais ces classes seraient internes à DAL. Lorsque le BLL demande des données à DAL, le DAL récupère les objets DAL requis dans la base de données (dalcustomer + daladdress) et construit une instance de EntCustomer à partir d'eux et le renvoie à BLL.
artokai

-1

DAL doit être indépendant de BL et BL dépendant de DAL. Votre interface utilisateur doit uniquement accéder aux données via BL. Il est recommandé de renvoyer DataTable ou DataRow à partir de DAL, puis de convertir DataTable / DataRow en objet (s) BL. Lorsque votre interface utilisateur doit accéder aux données, elle peut y accéder à partir de BL. L'interface utilisateur sera donc indépendante du nom de la colonne et du type de base de données (SQL Server, Oracle ..). De cette façon, votre interface utilisateur sera totalement indépendante de DAL. Personnellement, je préfère le nom de classe comme "CustomerBL", n'utilisez pas le mot BL dans la mendicité du nom de classe.

Voir ci-dessous un exemple de code.

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

Euh ... Cela ne signifie-t-il pas alors que votre BLL doit avoir connaissance du format / de la structure de vos tableaux de données? ...
Paul
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.