博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
解析三层架构(2)----分层究竟分出了那些东西
阅读量:6843 次
发布时间:2019-06-26

本文共 8836 字,大约阅读时间需要 29 分钟。

在上篇文章写到我们为什么要分层.有很多读者提出来很多宝贵的意见.让我受益匪浅,深深的感觉到自己的水平"还有很大的提升空间".首先感谢这些朋友们,我会进一步总结完善自己的想法.

截取了部分朋友的留言,感谢他们:

这次我用对比的方式描述一下,分层到底分出了什么.俗话说:有分必有合,那么它是把什么合到了一起.

首先写出两个没有分层的demo:

<1>查询信息demo

1: Public Class Form2
2:     Private sqlCon As String = "Data Source=LSH;Initial Catalog=ComputerLab;User ID=sa;Password=123456"
3:     '查询数据库信息信息
4:     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
5: 
6:         Dim conStr As New SqlConnection '数据库连接对象
7:         Dim sqlCom As SqlCommand        '数据库执行对象
8:         Dim Res As DialogResult         '消息提示框返回类型
9:         Dim dr As SqlDataReader         'dataReader对象
10:         Dim dt As New DataTable         'Datatable对象
11: 
12:         Dim sql As String = "select * from TableName where Name=@name"                   'sql插入语句
13:         conStr.ConnectionString = sqlCon                                '给数据库连接对象赋值
14:         sqlCom = New SqlCommand(sql, conStr)                            '给数据库执行对象赋值
15:         sqlCom.Parameters.Add("@name", SqlDbType.VarChar, TextBox1.Text)    '给sql语句参数赋值
16: 
17:         Res = MessageBox.Show("是否添加", "提示", MessageBoxButtons.OKCancel)
18:         '判断是否查询
19:         If Res = DialogResult.Yes Then
20:             Try
21:                 conStr.Open()
22:                 dr = sqlCom.ExecuteReader    '执行查询语句
23:                 dt.Load(dr)
24:             Catch ex As Exception
25:                 Throw ex
26:             Finally
27:                 If Not IsNothing(conStr) Then   '如果数据库打开,则关闭数据库
28:                     conStr.Close()
29:                 End If
30:             End Try
31:         End If
32: 
33:         MsgBox(dt.Rows.Count)   '显示查询到的行数
34:     End Sub
 
<2>添加信息demo
1: Public Class Form1
2:     Private sqlCon As String = "Data Source=LSH;Initial Catalog=ComputerLab;User ID=sa;Password=123456"
3:     '向数据库添加信息
4:     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
5:         Dim bln As Boolean = False      '存储返回值
6:         Dim conStr As New SqlConnection '数据库连接对象
7:         Dim sqlCom As SqlCommand        '数据库执行对象
8:         Dim Res As DialogResult         '消息提示框返回类型
9: 
10:         Dim sql As String = "insert into TableName(Name) value(@Name)"  'sql插入语句
11:         conStr.ConnectionString = sqlCon                                '给数据库连接对象赋值
12:         sqlCom = New SqlCommand(sql, conStr)                            '给数据库执行对象赋值
13:         sqlCom.Parameters.Add("@Name", SqlDbType.VarChar, TextBox1.Text) '给sql语句参数赋值
14: 
15:         Res = MessageBox.Show("是否添加", "提示", MessageBoxButtons.OKCancel)
16:         '判断是否同意插入
17:         If Res = DialogResult.Yes Then
18:             Try
19:                 conStr.Open()
20:                 bln = sqlCom.ExecuteNonQuery    '执行插入语句
21:             Catch ex As Exception
22:                 bln = False
23:             Finally
24:                 If Not IsNothing(conStr) Then   '如果数据库打开,则关闭数据库
25:                     conStr.Close()
26:                 End If
27:             End Try
28:         End If
29: 
30:         MsgBox(bln) '提示返回信息
31:     End Sub
32: End Class

上面的两个没有分层的代码,当然在功能的实现上是完全没有问题.但是这样设计带来了很多的危机:

(1):写这个模块的人必须是一个能力非常强的人,因为他需要操作数据库,理解业务逻辑

(2):如果有另为一个模块需要这两个操作数据库的方法,只能重写或者调用该窗体下的方法.

(3):如果业务逻辑稍有变动,就需要拆开这个模块,重新编写,对于重新设计的人来说这个模块的所有设计都是可见的,很是不安全.

(4):如果要更换或者改动数据库,结果就是每一个模块都要重新编写

(5):如果有另为一个和这个相似的工程,想要复用以前的东西,难度很大

对于一个公司来说,当然不希望发生这样的事情.所以,合理的分层,降低系统的耦合性是必要的.

第一步:把数据库操作提取出来.

对每一个表,把完全对他的操作单独写成类也就是我们的DAO,数据访问类

每一个表对应一个DAO,每个DAO里面包含该数据库的所有增,删,查,改操作.这样做的好处就是对数据库的操作完全独立,达到功能单一.降低了和其他模块的耦合,写代码的时候,程序员不需要了解业务逻辑.

而且,在维护上和扩展上,如果对数据库改动,就会有针对性的去修改DAO.

当然,在设计的时候,我们尽量去封装不变的操作,这样不但能减少代码量,而且能达到很好的复用效果.在数据库操作中,对于数据库的打开,执行,关闭基本上都是一样的.所以我们单独提取出来sqlHelper(数据库助手类)

 

1: Imports System.Data.SqlClient
2: Imports System.Configuration
3: 
4: ''' 
5: ''' 运行数据库
6: ''' 
7: Public Class SqlHelp
8:     Private cmd As SqlCommand   'sqlcommand对象
9:     Private con As SqlConnection    'sqlconnection对象
10:     Private dr As SqlDataReader     'sqlDataReader对象
11:     ''' 
12:     ''' 获取连接字符串
13:     ''' 
14:     ''' 
连接字符串
15:     ''' 
16:     Public Function GetCon() As SqlConnection
17:         Dim conStr As String
18:         conStr = System.Configuration.ConfigurationManager.AppSettings("ConnStr")
19: 
20:         con = New SqlConnection
21:         con.ConnectionString = conStr
22: 
23:         '打开数据库
24:         If (con.State = ConnectionState.Closed) Then
25:             con.Open()
26:         End If
27: 
28:         Return con
29: 
30:     End Function
31: 
32:     ''' 
33:     ''' 增 删 改方法
34:     ''' 
35:     ''' 数据库语句 活存储过程名
36:     ''' 参数数组
37:     ''' 数据库字符串 或者存储过程名 类型
38:     Public Function ExecuteNonQuery(ByVal sqlStr As String, ByVal Param() As SqlParameter, ByVal commandType As CommandType) As Boolean
39: 
40:         cmd = New SqlCommand(sqlStr, Me.GetCon)
41:         cmd.CommandType = commandType
42: 
43:         '添加参数
44:         If Param IsNot Nothing Then
45:             cmd.Parameters.AddRange(Param)
46:         End If
47: 
48:         '执行语句
49:         Try
50:             Return CBool(cmd.ExecuteNonQuery)
51:         Catch ex As Exception
52:             Return False
53:         Finally
54:             If Not IsNothing(con) Then
55:                 con.Close()
56:             End If
57:         End Try
58: 
59:     End Function
60: 
61:     ''' 
62:     ''' 查询
63:     ''' 
64:     ''' sql语句 或者存储过程名
65:     ''' 参数数组
66:     ''' 执行类型
67:     Public Function ExecuteQuery(ByVal sqlStr As String, ByVal Param() As SqlParameter, ByVal commandType As CommandType) As DataTable
68:         Dim dt As New DataTable
69:         cmd = New SqlCommand(sqlStr, Me.GetCon)
70:         cmd.CommandType = commandType
71: 
72:         '添加参数
73:         If Param IsNot Nothing Then
74:             cmd.Parameters.AddRange(Param)
75:         End If
76: 
77:         '执行语句
78:         Try
79:             dr = cmd.ExecuteReader
80:             dt.Load(dr)
81:         Catch ex As Exception
82:             Return Nothing
83:         Finally
84:             If Not IsNothing(con) Then
85:                 con.Close()
86:             End If
87:         End Try
88:         Return dt
89:     End Function
提取后数据库访问层代码如下:
1: Imports SqlHelper
2: Imports System.Data.SqlClient
3: Public Class DAL
4:     Private sqlHelper As New SqlHelp
5:     ''' 
6:     ''' 查询记录
7:     ''' 
8:     ''' 关键字
9:     ''' 
记录集
10:     ''' 
11:     Public Function SelectInfo(ByVal strSelect As String) As DataTable
12:         'sql查询语句
13:         Dim sql As String = "select * from TableName where Name=@name"
14:         '向sql参数中添加实参
15:         Dim Para() As SqlParameter = {
New SqlParameter("@name", strSelect)}
16:         '调用sqlhelper执行数据库操作
17:         Return sqlHelper.ExecuteQuery(sql, Para, Data.CommandType.Text)
18:     End Function
19:     ''' 
20:     ''' 添加记录
21:     ''' 
22:     ''' 记录信息
23:     ''' 
是否成功
24:     ''' 
25:     Public Function AddInfo(ByVal strAdd As String) As Boolean
26:         'sql插入语句
27:         Dim sql As String = "insert into TableName(Name) value(@Name)"
28:         '向sql参数中添加实参
29:         Dim Para() As SqlParameter = {
New SqlParameter("@name", strAdd)}
30:         '调用sqlhelper执行数据库操作
31:         Return sqlHelper.ExecuteNonQuery(sql, Para, Data.CommandType.Text)
32:     End Function
33: End Class

第二:根据业务逻辑,个人习惯和用例相对应,把相关的逻辑判断,比如添加记录在什么情况下判断,添加前要判断记录是否存在等放到BLL层.

但是对于数据的有效性校验一般还是放在UI层,也可以有其他更好的方法,这些我在以后会总结出来.

代码如下:

1: Public Class BLL
2:     Private dal As New DAL
3:     ''' 
4:     ''' 业务逻辑层,添加方法
5:     ''' 
6:     ''' 添加信息
7:     ''' 
8:     Public Sub Add(ByVal strAdd As String)
9:         '定义用于存储查询结果的记录集
10:         Dim dt As New DataTable
11:         '执行查询,判断添加的信息是否已经存在
12:         dt = dal.SelectInfo(strAdd)
13:         If dt.Rows.Count > 0 Then
14:             Throw New Exception("记录已存在")
15:         Else
16:             '添加记录,返回是否成功
17:             If dal.AddInfo(strAdd) = True Then
18:                 Throw New Exception("添加成功")
19:             Else
20:                 Throw New Exception("添加失败")
21:             End If
22:         End If
23: 
24:     End Sub
25: 
26: End Class
第三:剩下的UI层里,除了判断数据有效性以为,只要调用bll的添加方法就可以了.这样制作UI的人就会减轻了很大的压力,让他们专心做美工或者其他.

代码如下:

1: Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
2:         Dim bll As New BLL
3:         '调用bll层添加方法
4:         Try
5:             bll.Add(TextBox1.Text)
6:         Catch ex As Exception
7:             '显示添加结果给用户
8:             MessageBox.Show(ex.Message)
9:         End Try
10:     End Sub

当然三层方式还有其他一些技巧,比如为DAL加一层接口,用抽象工厂加反射的方法实现数据库的灵活操作,替换.这里先不叙述.

上述都是个人的一点总结,欢迎大家指导

 

接下文:解析三层架构(3)--

转载于:https://www.cnblogs.com/jpa2/archive/2011/05/14/2527705.html

你可能感兴趣的文章