在DAL和BLL层之间分离检索数据和业务对象


9

在发布此问题之前,我做了一些研究。在其他问题或帖子中,下面提供其中一个。我不清楚如何确定。

数据访问层中的业务对象

我有一个存储库,业务层调用该存储库以检索数据。例如,说我有以下BLL和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; }
}

如果BLL要检索Customer对象,它将在DAL中调用GetCustomerById(customerId)。

以下是我不清楚的问题:

  1. 我看不到如何确定DAL中的GetCustomerById应该返回哪个对象?它应该返回BllCustomer还是DalCustomer?

  2. 与客户关联的地址的检索(和/或转换为业务对象)应该在哪里?

如果DAL返回Dal对象,则检索和填写地址的逻辑只能在BLL中。如果DAL返回BLL对象,则检索和填写地址的逻辑可以在BLL或DAL中。当前,DAL正在返回业务对象,而填充它的逻辑在DAL中。

从我的阅读中,我猜没有对与错。从上面包含的链接中,有人说一种方式,其他人说另一种方式。但是,如何确定哪种方法最适合我的情况?

任何帮助,将不胜感激。


2
我的第一个问题是:这是旧版应用程序吗?有大量的ORM框架使这种代码过时了,我敦促您考虑使用这样的框架...
JDT 2015年

@JDT我不确定您的意思,我正在使用Entity Framework并遇到完全相同的问题。据我了解,您不应将ORM用作域对象,那么转换在哪里进行?

为什么您的ORM框架也不会返回域对象?
JDT 2015年

3
@JDT ORM(在这种情况下为EF)返回的实体类通常代表每个类一个数据库表。这通常与域类相似,但不一定相同。也许您只是在说可以将ORM类用作域类吗?我在很多地方都读过,这是禁止的。

Answers:


5

我看不到如何确定DAL中的GetCustomerById应该返回哪个对象?它应该返回BllCustomer还是DalCustomer?

它应该返回一个DalCustomer对象,返回一个BllCustomer对象将违反单一责任原则。您可以将DalCustomer对象视为业务层(或使用者)使用的接口或合同。实际上,如果DAL 返回了BllCustomer,则DAL必须迎合调用它或可能调用它的每个业务层对象。

与客户关联的地址的检索(和/或转换为业务对象)应该在哪里?

转换应在视图模型或管理器中完成。您需要中介来调用您的服务或数据访问组件。如果您有需要,可以在BllCustomer对象中进行转换。但是,例如,当您将DAL从MSSQL交换到Oracle时,您返回的对象(或接口)必须保持不变。

最好您的业务层还应该独立于数据层。业务层负责您的业务规则。在这里,您将使用验证框架来添加您的验证,以执行您的业务规则。


4

您的存储库应返回BLL或域对象。很有可能您根本不需要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或单独的类库是否应该公开接口而不是像这样的具体类Customer
约拉

1
不可以。它可以公开具体的类。存储库的接口将很有用
Ewan

3

通常,DAL不了解BLL。这样想,具有不同BLL的其他应用程序可以使用相同的DAL。同一公司的应付款管理系统应用程序/模块和应收账款应用程序将共享数据(客户,费用,付款等)。试图让一个DLL拥有多个BLL的知识将非常困难且不必要。这也将允许您更改数据存储,而不会影响BLL(只要不破坏接口)。

现在,您可以将DAL对象传递给BLL,也可以创建第三组对象:实体。这些将仅包含要一起传递的值。DAL将引用该实体并与您的存储/数据库进行交互,而BLL将处理所有逻辑并引用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
}

感谢您的评论。我同意你的看法。.我已经可以看到我们的DAL /(存储库)已经充满了逻辑,例如类型是否为A,然后从表B中检索数据,但是如果类型为C,然后从表中检索数据C.但是我对您使用EntCustomer的示例感到困惑。就我而言,DalCustomer是数据库中表的镜像。您能否提供更多示例,如何使用EntCustomer或为什么要使用它以及它的好处。我正在考虑更改DAL,以将DalObjects返回给BLL。Bll将挂起到Business Objs的转换,检索并填写嵌套的obj。
ShamirDaj 2014年

您能否提供更多反馈?
ShamirDaj 2014年

我认为Ent对象的目的只是在DAL和BLL之间传输数据。您的DAL类可以继续镜像db结构,但是这些类将在DAL内部。当BLL向DAL请求数据时,DAL将从数据库(dalcustomer + daladdress)中获取所需的DAL对象,并从中构造EntCustomer的实例,然后将其返回给BLL。
artokai 2014年

-1

DAL应该独立于BL,并且BL依赖于DAL。您的UI仅应通过BL访问数据。如果您从DAL返回DataTable或DataRow,然后将DataTable / DataRow转换为BL对象,则这是一个好习惯。当您的UI需要访问数据时,可以从BL访问。因此,UI将独立于列名和数据库类型(SQL Server,Oracle ..)。这样,您的用户界面将完全独立于DAL。我个人更喜欢类名称,例如“ CustomerBL”,不要在类名称的开头使用BL字。

下面请参见示例代码。

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

错误...那不是意味着您的BLL需要了解数据表的格式/结构吗?...
Paul
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.