现在我毫不怀疑项目中应该存在的3个层次:
> UI(表示层)
> BLL(业务逻辑层)
> DAL(数据访问层)
在UI中我放了所有的WinForms.必须还有一些逻辑用控件中的数据填充对象并将其传递给BLL层.
在DAL中,我想使用ADO.NET为数据操作添加类和方法,如:
public class OrderDAL { public OrderDAL() { } public int Add(Order order) { //...add order to database } public int Update(Order order) { //...update order in database } //...etc. }
问题在于BLL和问题 – 我应该使用数据传输对象在层之间传递数据,还是应该通过整个类?
如果我选择使用DTO,那么我将创建另外的公共类Order,它引用UI,BLL和DAL:
public class Order { public int Id { get; set; } public DateTime Date { get; set; } public string Number { get; set; } public string CustomerName { get; set; } public Order () { } }
并将逻辑分为BLL:
public class OrderBLL { public OrderBLL() { } public int Add(Order order) { OrderDAL orderDAL = new OrderDAL(); return orderDAL.Add(order); } public int Update(Order order) { OrderDAL orderDAL = new OrderDAL(); return orderDAL.Update(order); } //...etc. }
这种方法在不同名称下使用:here或here.
另一方面,一些“聪明人”和他们的追随者(如here)称之为Anemic Domain Model,并抱怨这是一个不应该使用的糟糕的设计和反模式.
专业人士:
> DTO可以很容易地通过设计来表示数据库表,
>它清晰明了,只包含数据库所需的字段,
> DAL不必参考BLL,
缺点:
>反模式(听起来可怕; P),
>违反OOP(方法中的分离属性),
>因为逻辑处于不同的类别,当某些事情发生变化时可能更难以维护.
所以,相反的方法是在层之间传递整个对象,比如here:没有DTO,只是BLL看起来像那样:
public class Order { public int Id { get; set; } public DateTime Date { get; set; } public string Number { get; set; } public string CustomerName { get; set; } public Order() { } public int Add() { OrderDAL orderDAL = new OrderDAL(); return orderDAL.Add(this); } public int Update(Order order) { OrderDAL orderDAL = new OrderDAL(); return orderDAL.Update(order); } }
专业人士:
>它是一个很好的封装对象,遵循OOP规则(我想;)).
>逻辑和属性都在一个地方,更易于维护和调试.
缺点:
>要使用该对象,DAL必须引用BLL(这不是3层图层应该如何做的,不是吗?).
> class可能包含一些未在Database中使用的字段,以及来自Database的某些字段(如Id)不代表“真实生活”对象.
所以,它看起来像我选择的任何东西,我会违反一些规则.那么什么是更好的方式,我应该选择哪个?也许还有其他方法我还没找到?
解决方法
我也不喜欢让模型对象对自己的持久性负责的想法.我更喜欢单独的持久层.为什么?模型对象并不总是需要持久化才有用.业务逻辑和功能与持久性正交.
如果你有两个层,就可以保持单向依赖图:持久性知道模型,但模型不知道持久性.如果模型对象负责持久性,则最终会产生循环依赖.如果没有持久性,您永远不能测试或使用模型对象.
我的建议?不要做DTO.打破一个单独的持久层.