您的位置:首页 > 数据库

三层架构之抽象工厂加反射----实现数据库转换

2011-03-25 10:23 435 查看
注意:文中代码有误,为保留历史痕迹在本文不做修改,正确代码详见《纠错

在做系统的时候有意识的用到了抽象工厂这个设计模式,主要解决的是数据库更换的问题。

下面就以简单的登录来逐步的分析一下这个模式。

经典的三层架构



数据库如下



1. 一般的数据库连接方式

界面层





1:  Public Class Login

2:      Private Sub btnLogin_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLogin.Click

3:          Dim LUser As New Entity.User

4:          Dim BCheck As New BLL.B_Login

5:          LUser.User_ID = txtName.Text

6:          LUser.User_Pwd = txtPwd.Text

7:          If BCheck.Check(LUser) = True Then

8:              MsgBox("登录成功!")

9:          Else

10:              MsgBox(“"登录失败!")

11:          End If

12:      End Sub

13:

14:      Private Sub btnCancle_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancle.Click

15:          End

16:      End Sub

17:  End Class


业务逻辑层

1:  Public Class B_Login

2:      Function Check(ByVal User As Entity.User) As Boolean

3:          Dim DaUser As New DAL.D_UserInfo

4:          Dim BlUser As New Entity.User

5:          Bluser.User_ID=User.ID

6:          BlUser = DaUser.Check(BlUser)

7:            If BlUser.User_Pwd = User.User_Pwd Then

8:               Return True

9:           Else

10:                Return False

11:           End If

12:        End Function

13:  End Class


数据持久层

1:  Imports System.Data.SqlClient

2:  Public Class D_UserInfo

3:  Dim ConnStr As String = "Data Source=******;Initial Catalog=Student;User ID=sa;Password=******"

4:      Dim conn As SqlConnection = New SqlConnection(ConnStr)

5:      Function Check(ByVal User As Entity.User) As Entity.User

6:          Dim sql As String = "select * from UserInfo where UserInfo=" & User.User_ID

7:          Dim cmd As SqlCommand = New SqlCommand(sql, conn)

8:          Dim read As SqlDataReader

9:          Try

10:              conn.Open()

11:              read = cmd.ExecuteReader

12:              User.User_ID = read.Item(0)

13:           User.User_Pwd = read.Item(1)

14:              Return User

15:          Catch ex As Exception

16:              User.User_Pwd = ""

17:              Return User

18:          End Try

19:      End Function

20:  End Class


2. 简单工厂



添加一个工厂类和一个接口

接口类

1:  Public Interface IUserInfo

2:      Function Check(ByVal IUser As Entity.User) As Entity.User

3:  End Interface


工厂类

1:  Imports [Interface]

2:  Public Class DFactory

3:      'Dim DataBase As String = "Access"

4:      Dim DataBase As String = "Sql"

5:      Function CreateUserInfo() As IUserInfo

6:          Dim DB As IUserInfo

7:          Select Case DataBase

8:              Case "Sql"

9:                  DB = New D_UserInfoSql

10:                  'Case "Access"

11:                  '    DB = New D_UserInfoAccess

12:          End Select

13:       Return DB

14:      End Function

15:  End Class


当然D_UserInfoSql实现接口,代码基本不变

当有新的数据库使用时候(例如Access数据库)可以将工厂中的注释部分添上,然后重新写Dal层就可以直接使用,但是这样的不足是还是需要再次编译工厂,利用反射可以解决这个问题。

3.抽象工厂加反射



工厂类

1:  Imports [Interface]

2:  Imports System.Reflection

3:  Public Class DFactory

4:      '抽象工厂加反射

5:      Dim DBString As String = System.Configuration.ConfigurationSettings.AppSettings("DBString")

6:      Function CreateUserInfo() As IUserInfo

7:          Return CType(Assembly.Load("DAL").CreateInstance("DAL.D_UserInfo" & DBString), IUserInfo)

8:      End Function

9:  End Class


数据持久层

1:  Imports System.Data.SqlClient

2:  Public Class D_UserInfoSql : Implements [Interface].IUserInfo

3:      'Dim ConnStr As String = "Data Source=******;Initial Catalog=Student;User ID=sa;Password=******"

4:      Dim ConnStr As String = System.Configuration.ConfigurationSettings.AppSettings("ConnStr")

5:      Dim conn As SqlConnection = New SqlConnection(ConnStr)

6:      Public Function Check(ByVal IUser As Entity.User) As Entity.User Implements [Interface].IUserInfo.Check

7:          Dim sql As String = "select * from UserInfo where UserInfo=" & IUser.User_ID

8:          Dim cmd As SqlCommand = New SqlCommand(sql, conn)

9:          Dim read As SqlDataReader

10:          Try

11:              conn.Open()

12:              read = cmd.ExecuteReader

13:           IUser.User_ID = read.Item(0)

14:              IUser.User_Pwd = read.Item(1)

15:              Return IUser

16:          Catch ex As Exception

17:              IUser.User_Pwd = ""

18:              Return IUser

19:          End Try

20:      End Function

21:  End Class


配置文件

1:    <appSettings>

2:      <add key="ConnStr" value ="Data Source=******;Initial Catalog=Student;User ID=sa;Password=******"></add>

3:      <add key="DBString" value ="Sql"></add>

4:    </appSettings>


添加两个Key,一个是连接数据库的字符串,一个是通过反射来产生不同数据库的Dal层的

这样一来就可以实现设计模式中的“开闭原则”,如果更换数据库只需要增加类(DAL),而不需要更改,更不需要重新编译。

PS:配置文件必须在界面层

1、 反射的写法:

objType=Assembly.Load(AssemblyPath).CreateInstance(className);其中:AssemblyPath指程序集名。className指命名空间.类名称。

2、 反射的一个原则:一切皆以UI层的bin文件夹中的dll名称为中心。(原因很简单:.net类加载的机制就是默认从本程序集的bin文件中找,所以bin文件夹中一定要有要加载的程序集的dll)。UI层中bin文件夹中dll叫什么名字AssemblyPath就使用什么名字,bin内部类的全名叫什么,className就写成什么全名。.net中的引用:加入对某个程序集的引用就能在程序集有变化时自动拷贝dll。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: