关于三层架构的深入理解

时间:2021-05-25 00:54:55
如题 谁有你们公司的真正的在开发的项目发我一份啊
我对三层理解不够深

 BLL有一个业务逻辑 需要调用两个DAL层的方法 那么这个方法 就要访问两次数据库? 为什么不为这个BLL的方法 单独写一个存储过程 从而直接去掉 DAL层 这样几乎可以保证 每个请求 都只调用一次数据库 减小各种压力。。。而且使用一个存储过程 好控制事务 我现在很喜欢用ORM 就是这个原因。。。

这个DAL到底是干什么的?如果按照上面的想法 这个DAL貌似废了。。。

还有个DAO层 据说他是对DAL的封装 不知道是干什么的。。。。

业务逻辑层 有人直接把UI界面的控件 DataGridView  什么Repeat直接传到 业务逻辑层 这。。和老师说的不一样啊。。。不是把数据 传到BLL层吗。。。

如果每个BLL的方法 都直接使用一个存储过程 那么 BLL中又没得写了 所有逻辑都跑到数据库中去了。。。。

我用WCF+EntityFramework是没有那么多事  直接写方法 方法内部直接用EntityFramework写查询什么的。。。

BLL是干什么的。。。。。弄不懂 。。。。是不是 对于我这种写没有什么业务的项目的人来说BLL就废了啊。。。

我自己 刚才琢磨了一个框架 感觉酷比了 不想用EntityFramework+WCF来写了  想用纯三层 来做个高效率的 因为这个项目老大说要面向所有网民  我想写好点  求大家 把三层的概念 再给说一下 感觉很难啊 他不像是 什么while if 会了就是会了 这个是琢磨的 。。。求大神回答

9 个解决方案

#1


关于三层架构的深入理解
不管是分层还是用其他的EF,多为了减少代码之间的偶合依赖。
UI+BLL+DAL  这三个换掉其中的一个 做到不影响其他两个。并且能快速切换。

#2


DA   为BLL提供数据操作

新闻有类别,新闻内容

类别有对应的DAL接口(添加、修改、删除、获取列表、获取某个信息)

新闻也有对应的DAL接口(添加、修改、删除、获取列表、获取某个信息)

BLL 业务逻辑层,说白了就是对DAL进行重写拓展(偶合性在这里体现)

我们可能根据时间字段来获取信息,也可以根据标题关键词来获取信息

public IList<newsinfor> getnewslist(datetime dt){
   .... 
    newsdal.getlist(...)
}
public IList<newsinfor> getnewslist(string cond){
   .... 
    newsdal.getlist(...)
}
这里调用的都是一个接口,但确可以实现不同的拓展

又如我们的创建,修改
ui的调用是
newsinfor _newsinfor=new newsinfor();
....
newsbll.create(_newsinfor)

bll
public boll create(newsinfor infor){
   return newsdal.create(infor)>0;
}
public boll create2(newsinfor infor,...){
   return newsdal.create(infor)>0;
}
public boll create3(newsinfor infor,...,...){
   return newsdal.create(infor)>0;
}
dal
create(newsinfor infor){
   sql="insert into(xxxx,..)value(@xxx...)"
}

如果哪天我们要对数据进行拓展,添加或修改其它字段,那我们这时是不是只用修改ui和dal的那个接口方法,而不是去更新bll中的N个重写方法

#3


分层的重点不是在于其代码的实现效率上,而是在于偶合性上,偶合性是优势就是便于维护管理,这里有个重要提示,目前DAL和Mode都是可以通过代码生成器直接从数据库中生成出来

#4


引用 2 楼 liuchaolin 的回复:
DA   为BLL提供数据操作

新闻有类别,新闻内容

类别有对应的DAL接口(添加、修改、删除、获取列表、获取某个信息)

新闻也有对应的DAL接口(添加、修改、删除、获取列表、获取某个信息)

BLL 业务逻辑层,说白了就是对DAL进行重写拓展(偶合性在这里体现)

我们可能根据时间字段来获取信息,也可以根据标题关键词来获取信息

public IList<newsinfor> getnewslist(datetime dt){
   .... 
    newsdal.getlist(...)
}
public IList<newsinfor> getnewslist(string cond){
   .... 
    newsdal.getlist(...)
}
这里调用的都是一个接口,但确可以实现不同的拓展

又如我们的创建,修改
ui的调用是
newsinfor _newsinfor=new newsinfor();
....
newsbll.create(_newsinfor)

bll
public boll create(newsinfor infor){
   return newsdal.create(infor)>0;
}
public boll create2(newsinfor infor,...){
   return newsdal.create(infor)>0;
}
public boll create3(newsinfor infor,...,...){
   return newsdal.create(infor)>0;
}
dal
create(newsinfor infor){
   sql="insert into(xxxx,..)value(@xxx...)"
}

如果哪天我们要对数据进行拓展,添加或修改其它字段,那我们这时是不是只用修改ui和dal的那个接口方法,而不是去更新bll中的N个重写方法

ui的调用是
newsinfor _newsinfor=new newsinfor();
....
newsbll.create(_newsinfor)

bll
public boll create(newsinfor infor){
   return newsdal.create(infor)>0;
}
public boll create2(newsinfor infor,...){
   return newsdal.create(infor)>0;
}
public boll create3(newsinfor infor,...,...){
   return newsdal.create(infor)>0;
}
dal
create(newsinfor infor){
   sql="insert into(xxxx,..)value(@xxx...)"
}
也就是说 一个业务逻辑层可能调用多个 数据访问层 
进行多次的数据修改 并且事务 很难控制啊。。。

#5


引用 4 楼 jiaoshiyao 的回复:
Quote: 引用 2 楼 liuchaolin 的回复:

DA   为BLL提供数据操作

新闻有类别,新闻内容

类别有对应的DAL接口(添加、修改、删除、获取列表、获取某个信息)

新闻也有对应的DAL接口(添加、修改、删除、获取列表、获取某个信息)

BLL 业务逻辑层,说白了就是对DAL进行重写拓展(偶合性在这里体现)

我们可能根据时间字段来获取信息,也可以根据标题关键词来获取信息

public IList<newsinfor> getnewslist(datetime dt){
   .... 
    newsdal.getlist(...)
}
public IList<newsinfor> getnewslist(string cond){
   .... 
    newsdal.getlist(...)
}
这里调用的都是一个接口,但确可以实现不同的拓展

又如我们的创建,修改
ui的调用是
newsinfor _newsinfor=new newsinfor();
....
newsbll.create(_newsinfor)

bll
public boll create(newsinfor infor){
   return newsdal.create(infor)>0;
}
public boll create2(newsinfor infor,...){
   return newsdal.create(infor)>0;
}
public boll create3(newsinfor infor,...,...){
   return newsdal.create(infor)>0;
}
dal
create(newsinfor infor){
   sql="insert into(xxxx,..)value(@xxx...)"
}

如果哪天我们要对数据进行拓展,添加或修改其它字段,那我们这时是不是只用修改ui和dal的那个接口方法,而不是去更新bll中的N个重写方法

ui的调用是
newsinfor _newsinfor=new newsinfor();
....
newsbll.create(_newsinfor)

bll
public boll create(newsinfor infor){
   return newsdal.create(infor)>0;
}
public boll create2(newsinfor infor,...){
   return newsdal.create(infor)>0;
}
public boll create3(newsinfor infor,...,...){
   return newsdal.create(infor)>0;
}
dal
create(newsinfor infor){
   sql="insert into(xxxx,..)value(@xxx...)"
}
也就是说 一个业务逻辑层可能调用多个 数据访问层 
进行多次的数据修改 并且事务 很难控制啊。。。

你说的没错,其实这是因为DAL做了太多的不属于自己的事导致的

#6


写了这么多年都不知道3层架构到底是个什么东西。

#7


引用 1 楼 wyd1520 的回复:
关于三层架构的深入理解
不管是分层还是用其他的EF,多为了减少代码之间的偶合依赖。
UI+BLL+DAL  这三个换掉其中的一个 做到不影响其他两个。并且能快速切换。


其实 参透1楼的话 就可以了
什么Repeater传到业务层 那是胡闹的


引用 楼主 jiaoshiyao 的回复:
...
BLL有一个业务逻辑 需要调用两个DAL层的方法 那么这个方法 就要访问两次数据库? 为什么不为这个BLL的方法 单独写一个存储过程 从而直接去掉 DAL层 这样几乎可以保证 每个请求 都只调用一次数据库 减小各种压力。。。而且使用一个存储过程 好控制事务 我现在很喜欢用ORM 就是这个原因。。。
....

如果你直接写存储过程来解决这个问题 我只能说不是不行 而你写出来的东西 就不是三层架构这种概念的框架了
还是1楼的话 你写道存储过程中了 如果 有一天 你的数据要迁移到不支持存储过程的DB中去 你又要如何 就不紧紧是迁移数据的事了 解决方案是 你可以在DAL中提供一个方法 返回的数据是FA和FB数据的并集 只访问一次数据库 这里只是个例子 不是标准 总之 在不违背分层架构的理念来说 你总是有办法来进行优化的

不得不提的是 很多三层的场景 你是可以把代码级别的DAL与数据库捆绑起来看作DAL的 SQL来说 写存储过程从多方面来讲就是比在代码中写sql要好 这样 就不得不把数据库划分一半到DAL 另一半是数据存储 只是划分的角度而以 虽然这也有违背分层架构的初衷 但很多场景是不得不这样做 我们需要考量的 不仅仅是代码质量 也要考量性能指标 耦合度的增加 也在所难免 只能是尽量降低 你用EF也好 用DAL也好 只是EF把DAL与DB的耦合透明化了 实际没有降低 迁移的时候 你面临的问题是一样的

分层的要点 还是要理解1楼所说的理念 如果你觉得分三层都多 有的方法只是简单的return更底层的结果 其实 多数的情况也确实如此 但这里要说的是 这个看似浪费的拆分 是有必要的 就说中间的受气包BLL 通常是UI请求它 它return DAL的M_A方法的结果 设么都不做 确实挺2B的 但有一天 你的业务逻辑变更了 你可能需要更加丰富的数据返回 可是直接更改M_A 是有很大风险的 你不知道都有哪些BLL需要它(当然 BLL也有这样的风险 但毕竟比DAL可控性高 如果你划分合理的话) 那你可以很轻松的更改BLL的逻辑 而不至于对其他BLL逻辑造成影响  其实 说了半天 也就是松散耦合的东西 举例而已 理解是关键

#8


扔掉你的数据库,只是使用内存对象,例如List<T>,你就可以写好BLL层。这可以撇清对数据库的那种纠结。

而你的服务器端可以针对完全异构的客户端交互界面处理,都可以使用同一套BLL接口,并且系统的核心业务逻辑又BLL层控制(例如你必须通过移动公司的网络打电话,你不可能用自己的鞋子打电话),这时候你就是在用BLL来“挺起”你的架构了。而不是那种无头苍蝇一样地简单做点OA界面了。

#9


引用 8 楼 sp1234 的回复:
扔掉你的数据库,只是使用内存对象,例如List<T>,你就可以写好BLL层。这可以撇清对数据库的那种纠结。

而你的服务器端可以针对完全异构的客户端交互界面处理,都可以使用同一套BLL接口,并且系统的核心业务逻辑又BLL层控制(例如你必须通过移动公司的网络打电话,你不可能用自己的鞋子打电话),这时候你就是在用BLL来“挺起”你的架构了。而不是那种无头苍蝇一样地简单做点OA界面了。


有道理的,只是扔掉数据库,就可以写好 DAL层了。笔误了。

#1


关于三层架构的深入理解
不管是分层还是用其他的EF,多为了减少代码之间的偶合依赖。
UI+BLL+DAL  这三个换掉其中的一个 做到不影响其他两个。并且能快速切换。

#2


DA   为BLL提供数据操作

新闻有类别,新闻内容

类别有对应的DAL接口(添加、修改、删除、获取列表、获取某个信息)

新闻也有对应的DAL接口(添加、修改、删除、获取列表、获取某个信息)

BLL 业务逻辑层,说白了就是对DAL进行重写拓展(偶合性在这里体现)

我们可能根据时间字段来获取信息,也可以根据标题关键词来获取信息

public IList<newsinfor> getnewslist(datetime dt){
   .... 
    newsdal.getlist(...)
}
public IList<newsinfor> getnewslist(string cond){
   .... 
    newsdal.getlist(...)
}
这里调用的都是一个接口,但确可以实现不同的拓展

又如我们的创建,修改
ui的调用是
newsinfor _newsinfor=new newsinfor();
....
newsbll.create(_newsinfor)

bll
public boll create(newsinfor infor){
   return newsdal.create(infor)>0;
}
public boll create2(newsinfor infor,...){
   return newsdal.create(infor)>0;
}
public boll create3(newsinfor infor,...,...){
   return newsdal.create(infor)>0;
}
dal
create(newsinfor infor){
   sql="insert into(xxxx,..)value(@xxx...)"
}

如果哪天我们要对数据进行拓展,添加或修改其它字段,那我们这时是不是只用修改ui和dal的那个接口方法,而不是去更新bll中的N个重写方法

#3


分层的重点不是在于其代码的实现效率上,而是在于偶合性上,偶合性是优势就是便于维护管理,这里有个重要提示,目前DAL和Mode都是可以通过代码生成器直接从数据库中生成出来

#4


引用 2 楼 liuchaolin 的回复:
DA   为BLL提供数据操作

新闻有类别,新闻内容

类别有对应的DAL接口(添加、修改、删除、获取列表、获取某个信息)

新闻也有对应的DAL接口(添加、修改、删除、获取列表、获取某个信息)

BLL 业务逻辑层,说白了就是对DAL进行重写拓展(偶合性在这里体现)

我们可能根据时间字段来获取信息,也可以根据标题关键词来获取信息

public IList<newsinfor> getnewslist(datetime dt){
   .... 
    newsdal.getlist(...)
}
public IList<newsinfor> getnewslist(string cond){
   .... 
    newsdal.getlist(...)
}
这里调用的都是一个接口,但确可以实现不同的拓展

又如我们的创建,修改
ui的调用是
newsinfor _newsinfor=new newsinfor();
....
newsbll.create(_newsinfor)

bll
public boll create(newsinfor infor){
   return newsdal.create(infor)>0;
}
public boll create2(newsinfor infor,...){
   return newsdal.create(infor)>0;
}
public boll create3(newsinfor infor,...,...){
   return newsdal.create(infor)>0;
}
dal
create(newsinfor infor){
   sql="insert into(xxxx,..)value(@xxx...)"
}

如果哪天我们要对数据进行拓展,添加或修改其它字段,那我们这时是不是只用修改ui和dal的那个接口方法,而不是去更新bll中的N个重写方法

ui的调用是
newsinfor _newsinfor=new newsinfor();
....
newsbll.create(_newsinfor)

bll
public boll create(newsinfor infor){
   return newsdal.create(infor)>0;
}
public boll create2(newsinfor infor,...){
   return newsdal.create(infor)>0;
}
public boll create3(newsinfor infor,...,...){
   return newsdal.create(infor)>0;
}
dal
create(newsinfor infor){
   sql="insert into(xxxx,..)value(@xxx...)"
}
也就是说 一个业务逻辑层可能调用多个 数据访问层 
进行多次的数据修改 并且事务 很难控制啊。。。

#5


引用 4 楼 jiaoshiyao 的回复:
Quote: 引用 2 楼 liuchaolin 的回复:

DA   为BLL提供数据操作

新闻有类别,新闻内容

类别有对应的DAL接口(添加、修改、删除、获取列表、获取某个信息)

新闻也有对应的DAL接口(添加、修改、删除、获取列表、获取某个信息)

BLL 业务逻辑层,说白了就是对DAL进行重写拓展(偶合性在这里体现)

我们可能根据时间字段来获取信息,也可以根据标题关键词来获取信息

public IList<newsinfor> getnewslist(datetime dt){
   .... 
    newsdal.getlist(...)
}
public IList<newsinfor> getnewslist(string cond){
   .... 
    newsdal.getlist(...)
}
这里调用的都是一个接口,但确可以实现不同的拓展

又如我们的创建,修改
ui的调用是
newsinfor _newsinfor=new newsinfor();
....
newsbll.create(_newsinfor)

bll
public boll create(newsinfor infor){
   return newsdal.create(infor)>0;
}
public boll create2(newsinfor infor,...){
   return newsdal.create(infor)>0;
}
public boll create3(newsinfor infor,...,...){
   return newsdal.create(infor)>0;
}
dal
create(newsinfor infor){
   sql="insert into(xxxx,..)value(@xxx...)"
}

如果哪天我们要对数据进行拓展,添加或修改其它字段,那我们这时是不是只用修改ui和dal的那个接口方法,而不是去更新bll中的N个重写方法

ui的调用是
newsinfor _newsinfor=new newsinfor();
....
newsbll.create(_newsinfor)

bll
public boll create(newsinfor infor){
   return newsdal.create(infor)>0;
}
public boll create2(newsinfor infor,...){
   return newsdal.create(infor)>0;
}
public boll create3(newsinfor infor,...,...){
   return newsdal.create(infor)>0;
}
dal
create(newsinfor infor){
   sql="insert into(xxxx,..)value(@xxx...)"
}
也就是说 一个业务逻辑层可能调用多个 数据访问层 
进行多次的数据修改 并且事务 很难控制啊。。。

你说的没错,其实这是因为DAL做了太多的不属于自己的事导致的

#6


写了这么多年都不知道3层架构到底是个什么东西。

#7


引用 1 楼 wyd1520 的回复:
关于三层架构的深入理解
不管是分层还是用其他的EF,多为了减少代码之间的偶合依赖。
UI+BLL+DAL  这三个换掉其中的一个 做到不影响其他两个。并且能快速切换。


其实 参透1楼的话 就可以了
什么Repeater传到业务层 那是胡闹的


引用 楼主 jiaoshiyao 的回复:
...
BLL有一个业务逻辑 需要调用两个DAL层的方法 那么这个方法 就要访问两次数据库? 为什么不为这个BLL的方法 单独写一个存储过程 从而直接去掉 DAL层 这样几乎可以保证 每个请求 都只调用一次数据库 减小各种压力。。。而且使用一个存储过程 好控制事务 我现在很喜欢用ORM 就是这个原因。。。
....

如果你直接写存储过程来解决这个问题 我只能说不是不行 而你写出来的东西 就不是三层架构这种概念的框架了
还是1楼的话 你写道存储过程中了 如果 有一天 你的数据要迁移到不支持存储过程的DB中去 你又要如何 就不紧紧是迁移数据的事了 解决方案是 你可以在DAL中提供一个方法 返回的数据是FA和FB数据的并集 只访问一次数据库 这里只是个例子 不是标准 总之 在不违背分层架构的理念来说 你总是有办法来进行优化的

不得不提的是 很多三层的场景 你是可以把代码级别的DAL与数据库捆绑起来看作DAL的 SQL来说 写存储过程从多方面来讲就是比在代码中写sql要好 这样 就不得不把数据库划分一半到DAL 另一半是数据存储 只是划分的角度而以 虽然这也有违背分层架构的初衷 但很多场景是不得不这样做 我们需要考量的 不仅仅是代码质量 也要考量性能指标 耦合度的增加 也在所难免 只能是尽量降低 你用EF也好 用DAL也好 只是EF把DAL与DB的耦合透明化了 实际没有降低 迁移的时候 你面临的问题是一样的

分层的要点 还是要理解1楼所说的理念 如果你觉得分三层都多 有的方法只是简单的return更底层的结果 其实 多数的情况也确实如此 但这里要说的是 这个看似浪费的拆分 是有必要的 就说中间的受气包BLL 通常是UI请求它 它return DAL的M_A方法的结果 设么都不做 确实挺2B的 但有一天 你的业务逻辑变更了 你可能需要更加丰富的数据返回 可是直接更改M_A 是有很大风险的 你不知道都有哪些BLL需要它(当然 BLL也有这样的风险 但毕竟比DAL可控性高 如果你划分合理的话) 那你可以很轻松的更改BLL的逻辑 而不至于对其他BLL逻辑造成影响  其实 说了半天 也就是松散耦合的东西 举例而已 理解是关键

#8


扔掉你的数据库,只是使用内存对象,例如List<T>,你就可以写好BLL层。这可以撇清对数据库的那种纠结。

而你的服务器端可以针对完全异构的客户端交互界面处理,都可以使用同一套BLL接口,并且系统的核心业务逻辑又BLL层控制(例如你必须通过移动公司的网络打电话,你不可能用自己的鞋子打电话),这时候你就是在用BLL来“挺起”你的架构了。而不是那种无头苍蝇一样地简单做点OA界面了。

#9


引用 8 楼 sp1234 的回复:
扔掉你的数据库,只是使用内存对象,例如List<T>,你就可以写好BLL层。这可以撇清对数据库的那种纠结。

而你的服务器端可以针对完全异构的客户端交互界面处理,都可以使用同一套BLL接口,并且系统的核心业务逻辑又BLL层控制(例如你必须通过移动公司的网络打电话,你不可能用自己的鞋子打电话),这时候你就是在用BLL来“挺起”你的架构了。而不是那种无头苍蝇一样地简单做点OA界面了。


有道理的,只是扔掉数据库,就可以写好 DAL层了。笔误了。