在对Dao层进行设计时采用过两种方案:
方案一:每一表对应一个Dao类(接口也可),每个Dao将完成对该表的增删改查以及业务上要求的查询操作。这么设计的话如果表很多的话将会产生很多类,并且将会出现大量重复的代码,因为每一个Dao中都将涉及到基础的增删改查。
方案二:写一个基础的类,可以完成基本的增删改查,其他的对于业务上有额外需求的表单独在写一个类,不过这个类只包括额外的功能。这里的基础类写的时候是需要严格注意的,因为采用的类似映射的实现,需要你把实体类设计的同表结构一摸一样,因为在该类中对数据库的增删改查的Sql语句就是通过对实体类类名以及对实体类类中属性的提取完形成的。
这里给出一个基本的添加方法(vb.net实现):
Public Class SqlDao : Implements Dal.IDao
Private SqlDr As SqlDataReader
Private SqlCon As SqlConnection
Private SqlCmd As SqlCommand
'从配置文件app.config中取得连接数据库的字符串
Private strConnect As String = ConfigurationManager.AppSettings("strCon")
'得到类名
Private strClassName As String
'得到类的类型
Private mType As Type
'得到属性集
Private mProS As PropertyInfo()
'在初始化方法中连接数据库
'Public Sub Init(ByVal obj As Object) Implements IDao.Init
' SqlCon = New SqlConnection(strConnect)
' '在构造函数中对必要类型进行初始化
' strClassName = TypeName(obj)
' mType = obj.GetType()
' mProS = mType.GetProperties
'End Sub
'连接数据库的一个私有方法
Private Function GetCon() As SqlConnection Implements IDao.GetCon
Try
If (SqlCon.State = ConnectionState.Closed) Then
SqlCon.Open()
End If
Catch ex As Exception
MsgBox("打开数据库时:" + ex.Message)
End Try
Return SqlCon
End Function
'''
''' 将对象添加到对应的表中,参数为对象,返回值为Int型,表示影响的行数
'''
'''
'''Integer
'''
Public Function AddObj(Of T)(ByVal Entity As T) As Integer Implements IDao.AddObj
Dim res As Integer = 0 '用来返回该操作影响的行数
'定义单个属性
Dim mPro As PropertyInfo
'定义sql参数
Dim para As SqlParameter
Dim strFields As String = ""
Dim strCondition As String = ""
Dim strSql As String = ""
For Each mPro In mProS
'该循环用来进行参数组合
'再添加时不用添加时间
strFields = CStr(Trim(mPro.GetValue(Entity, Nothing))) '获取属性值
If strFields <> "0" And strFields <> "00:00:00" And strFields <> "" Then
strSql = strSql + "@" + mPro.Name + ","
'组合形成字段名
strCondition = strCondition + mPro.Name + ","
End If
Next
'最后再插入最后的括号
strSql = Left(strSql, Len(strSql) - 1) + ")"
strCondition = Left(strCondition, Len(strCondition) - 1) + ")"
strSql = "INSERT INTO " + strClassName + " (" + strCondition + " VALUES (" + strSql
'MsgBox(strSql)
Try
Using sCmd As New SqlCommand(strSql, GetCon)
'设定执行方式
sCmd.CommandType = CommandType.Text
For Each mPro In mProS
'进行参数的赋值
'Dim stra As String = mPro.GetValue(obj, Nothing)
'一般的添加不用加入时间,除了下机表
strFields = CStr(Trim(mPro.GetValue(Entity, Nothing))) '获取属性值
If strFields <> "0" And strFields <> "00:00:00" And strFields <> "" Then
para = New SqlParameter("@" + mPro.Name, mPro.GetValue(Entity, Nothing))
sCmd.Parameters.Add(para)
End If
Next
res = sCmd.ExecuteNonQuery
End Using
Catch ex As Exception
MsgBox("进行对象添加时:" + ex.Message)
End Try
Return res '返回该操作影响的行数
End Function
End Class
这几天从网上也查了一些资料主要就是关于Dao层该如何设计的问题,最直接的设计方案就是每一个表对应一个Dao,说是代码重复太多,不过这样设计那些基本的代码是不用写的,都有现成的工具,直接根据表生成对应的增删改查。
不过因为需要重复的代码太多了,因此有人提出这种方法:
public interface BaseDao{
public void create (T t);
public void delete (T t);
public void update (T t);
}
public interface WindDao extends BaseDao{
public void other (Wind wind);
}
将基本的增删改查通过泛型放置到一个基础的接口中,其他的只需实现该接口,如果有额外的需求便可自行添加方法。这可谓一个典型的继承的应用。不过说实话,这种方法也不能使代码量减少。
这块还真是不太明白,论坛里有人说:“其实可以将basedao注入baseservice来实现,这样就不用每个dao都写一个类了”,实在是理解不了,如果有大牛恰好经过劳烦指点一二,不胜感激。
曹师哥点拨:
遇到一个问题,我会采用软件工程上的3w原则(what,why,how)来思考。
首先what:
why:
how:通过以上的why的分析,我们在设计dao层的时候,要注意:
总之,使用dao层,使得业务的操作跟数据库的操作进行了解耦,业务的变化不会影响数据的访问,而数据访问方式的改变(保证接口不变),不会影响业务,使得系统的各个部分相互独立。dao层的操作是对业务的一个分解,把一个完整的业务分解到数据库中的相关表中。
- from the5fire.com
----EOF-----
微信公众号:Python程序员杂谈
微信公众号:Python程序员杂谈