vb.net版机房收费——助你学会七层架构(二)反射+抽象工厂
上一篇咱们做好了准备工作,数据库设计和Entity层,现在介绍 4、反射+抽象工厂 反射:用来消除Switch和if的,这里我尽量简单地介绍,以便大家理解。反射其实用起来很简单,你就认为他就是决定:去某个地方找应该要实例化的类是哪个。怎么理解?
'************************** '文 件 名:DataAccess '命名空间:Factory '内 容: '功 能: '文件关系: '作 者:邱慕夏 '小 组:邱慕夏 '生成日期:2014-06-09 9:17:51 '版 本 号:V1.0.0.0 '修改日志: '版权说明: '*************************** Imports System.Reflection Imports IDAL Public Class DataAccess Dim strDB As String = System.Configuration.ConfigurationSettings.AppSettings("DBUser") '这里修改配置文件就可以确定是查询那个表了。 Dim StrQueryWorkLog As String = System.Configuration.ConfigurationSettings.AppSettings("DBStrQueryWorkLog") '/// <summary> '/// depiction:<实例化一个DAL中的User表的类> '/// </summary> '/// <param name="<参数名称>"><参数说明></param> '/// <returns> '///<返回值是一个boolean值> '/// </returns> Public Function CreateUserInfo() As IDAL.IUser Return CType(Assembly.Load("DAL").CreateInstance("DAL" & "." & strDB),IUser) End Function '/// <summary> '/// depiction:<实例化一个DAL中的WorkLog表的类> '/// </summary> '/// <param name="<参数名称>"><参数说明></param> '/// <returns> '///<返回值是要实例化的表> '/// </returns> Public Function CreateWorkLog() As IDAL.IWorkLog Return CType(Assembly.Load("DAL").CreateInstance("DAL" & "." & StrQueryWorkLog),IWorkLog) End Function End Class 我给大家写完整就是这样的。DAL是D层命名空间,DAL.表名,是这个意思。StrQueryWroklog其实这个值说白了就是一个变量,放在配置文件里了,你就觉得好像很高大上一样,其实不然,个人认为这里完全可以改为: Dim strQueryWorkLog As String = "WorklogDAL" 就是两个变量而已,不用害怕,想用配置文件,之后,我会给大家细说,现在由于篇幅问题,就不写配置文件了,大家把上面的两行代码: Dim strDB As String = System.Configuration.ConfigurationSettings.AppSettings("DBUser") Dim StrQueryWorkLog As String = System.Configuration.ConfigurationSettings.AppSettings("DBStrQueryWorkLog") 改成我上面写得 Dim strQueryWorkLog As String = "WorklogDAL" Dim strDB As String = "LoginDAL" 完全没有影响,嘿嘿。
5、D层的构建 D层理解起来很简单就是针对数据库的增删改查就行了,但我们用的是面向对象的语言,所以我们就要考虑代码的复用问题,重复的代码我们给它分类。记住:分类是为了抽象;我们给它抽象出来一个SQLHelper分为四类:查询返回boolean、查询返回实体、增删改返回boolean、增删改返回实体。 抽象出来的sqlhelper我就只写一下Login功能需要的,User表查询分会boolean、worklog增删改返回boolean。(因为它们都不需要返回实体)。
'************************** '文 件 名:SqlHelper '命名空间:DAL '内 容: '功 能: '文件关系: '作 者:邱慕夏 '小 组:邱慕夏 '生成日期:2014-06-07 14:47:28 '版 本 号:V1.0.0.0 '修改日志: '版权说明: '*************************** Imports System.Data.SqlClient Imports System.Configuration Public Class SqlHelper Dim strConnection As String = System.Configuration.ConfigurationManager.AppSettings("strConnection") '定义连接 Dim conn As SqlConnection '定义命令 Dim cmd As SqlCommand '初始化连接对象 Public Sub New() conn = New SqlConnection(strConnection) End Sub '------------------------------------------ '执行增删改三个,不需要返回实体类型,返回Boolean类型,True为返回成功,反之,返回失败 '应用存储过程 '------------------------------------------ '/// <summary> '/// depiction:<增删改功能,但不传回参数> '/// </summary> '/// <param name="<参数名称>"><参数说明></param> '/// <returns> '///<返回值是boolean类型的,就是说成功了传回的就是True,没有修改成功的为False> ' /// </returns> Public Function ExecuteNonQuery(ByVal strText As String,ByVal cmdType As CommandType,ByVal sqlParams As SqlParameter()) As Boolean Dim cmd As New SqlCommand cmd.CommandText = strText '命令文本 cmd.CommandType = cmdType '命令类型 cmd.Connection = conn '连接数据库 cmd.Parameters.AddRange(sqlParams) '传参 Dim flag As Boolean = False '定义返回值 Try conn.Open() flag = cmd.ExecuteNonQuery() cmd.Parameters.Clear() Return flag Catch ex As Exception flag = False Finally Call CloseConnection(conn) Call CloseCmd(cmd) End Try Return flag End Function '/// <summary> '/// depiction:<查询功能,不传回参数> '/// </summary> '/// <param name="<参数名称>"><参数说明></param> '/// <returns> '///<返回值是boolean类型的,就是说成功了传回的就是True,没有修改成功的为False> ' /// </returns> Public Function ExecuteQuery(ByVal strText As String,ByVal sqlParams As SqlParameter()) As Boolean Dim cmd As New SqlCommand cmd.CommandText = strText '命令文本 cmd.CommandType = cmdType '命令类型是存储过程 cmd.Connection = conn '连接数据库 Dim reader As SqlClient.SqlDataReader '读取数据库中的表 cmd.Parameters.AddRange(sqlParams) '传参 Dim flag As Boolean = False '定义返回值 Try conn.Open() reader = cmd.ExecuteReader() flag = reader.Read() Catch ex As Exception flag = False MsgBox("查询失败",CType(vbOKOnly + MsgBoxStyle.Exclamation,MsgBoxStyle),"警告") Finally Call CloseConnection(conn) Call CloseCmd(cmd) End Try Return flag End Function '/// <summary> '/// depiction:<关闭命令> '/// </summary> '/// <param name="<参数名称>"><参数说明></param> '/// <returns> '///<返回为> ' /// </returns> Public Sub CloseCmd(ByVal cmd As SqlCommand) If Not IsNothing(cmd) Then '判断是否为空 cmd.Dispose() '销毁 cmd = Nothing End If End Sub '/// <summary> '/// depiction:<关闭连接> '/// </summary> '/// <param name="<参数名称>"><参数说明></param> '/// <returns> '///<返回为> ' /// </returns> Public Sub CloseConnection(ByVal conn As SqlConnection) If Not IsNothing(conn.State <> ConnectionState.Closed) Then conn.Close() '关闭连接 conn = Nothing End If End Sub End Class 不难看出,我只在这里用了两个,多了大家不容易接受,好的,这里说一下:好的注释能让你一眼看到这个function的功能。所以我们一定要写好注释。 SQLHelper我把它放在D层,同样放在D层的是针对各个表进行操作的函数。我的D层是按照表来划分的,给大家看一下,有个宏观把握:
需要注意的是SqlHelper放在D层,我们需要的表LoginDAL表和WorkLogDAL表,还有一个QueryStudentDAL不是表,是一个视图,我也放在这里了。 大家一定要先建SqlHelper,在建LoginDAL和WorkLogDAL,两个表代码:
'************************** '文 件 名:Login '命名空间:DAL '内 容: '功 能: '文件关系: '作 者:邱慕夏 '小 组:邱慕夏 '生成日期:2014-06-07 17:25:05 '版 本 号:V1.0.0.0 '修改日志: '版权说明: '*************************** Imports IDAL Imports System.Data.SqlClient Public Class LoginDAL : Implements IDAL.IUser '/// <summary> '/// depiction:<登陆功能,调用sqlhelper,放在DAL层> '/// </summary> '/// <param name="<参数名称>"><参数说明></param> '/// <returns> '///<对方法返回值的说明,该说明必须明确说明返回的值代表什么含义> ' /// </returns> '/// <summary> '/// depiction:<修改密码之前,先要验证一下密码是否正确> '/// </summary> '/// <param name="<参数名称>"><参数说明></param> '/// <returns> '///<返回boolean即可> ' /// </returns> Public Function User_Login(user As Entity.LoginEntity) As DataTable Implements IUser.User_Login Dim sqlparams As SqlParameter() = {New SqlParameter("@UserID",user.UserID),New SqlParameter("@Password",user.Password)} Dim cmdText As String = "sp_SelectUser" Dim helper As New SqlHelper '实例化SqlHelper Dim cmdType As CommandType = New CommandType() cmdType = CommandType.StoredProcedure '定义命令类型为存储过程 Dim table As New DataTable table = helper.ExecuteQueryVar(cmdText,cmdType,sqlparams) '定义返回值 Return table End Function end Class
'************************** '文 件 名:WorkLogDAL '命名空间:DAL '内 容: '功 能: '文件关系: '作 者:邱慕夏 '小 组:邱慕夏 '生成日期:2014/6/15 11:17:48 '版 本 号:V1.0.0.0 '修改日志: '版权说明: '*************************** Imports IDAL Imports System.Data.SqlClient '/// <summary> '/// depiction:<实例化一个IDAL中的worklog类,登陆的时候,顺便记录进去> '/// </summary> '/// <param name="<参数名称>"><参数说明></param> '/// <returns> '///<返回值是一个boolean值> '/// </returns> Public Function SaveWorkLog(worklog As Entity.WorkLogEntity) As Boolean Implements IWorkLog.SaveWorkLog Dim strText As String = "INSERT INTO T_WorkLog(UserID,Level,LoginDateTime,Computer,Status) VALUES(@UserID,@Level,@LoginDateTime,@Computer,@Status)" Dim sqlparams As SqlParameter() = {New SqlParameter("@UserID",worklog.UserID),New SqlParameter("@Level",Entity.LoginEntity.UserLevel),New SqlParameter("@LoginDateTime",worklog.LoginDateTime),New SqlParameter("@Computer",worklog.Computer),New SqlParameter("@Status",worklog.Status)} Dim cmdType As CommandType = CommandType.Text Dim helper As New SqlHelper Return helper.ExecuteNonQuery(strText,sqlparams) End Function End Class
Dim cmdText As String = "sp_SelectUser" 这个是存储过程的名字,那我们怎么知道它是存储过程的,看这一行: Dim cmdType As CommandType = New CommandType() 这两行,就告诉我们是存储过程,它们是对应的,那么我不想用存储过程,我想用sql语句怎么办: Dim strText As String = "INSERT INTO T_WorkLog(UserID,@Status)" 这是Worklog中的一段,后面我们很熟悉,就是增加一条数据,跟存储过程不用,它和: Dim cmdType As CommandType = CommandType.Text 是对应的,大家一定不要搞混了。 好了里面的我们都弄清了,那我们怎么告诉SqlHelper我们的参数、sql语句、存储过程等。大家看: Return helper.ExecuteNonQuery(strText,sqlparams) 这句话,就是调用sqlhelper,helper是实例了一个sqlhelper的名字,return返回helper返回的东西(boolean),其实这里helper的这个函数就是返回boolean,所以我懒省事就这样写了,一样的,分开写就是这样的: dim flag as boolean=helper.ExecuteNonQuery(strText,sqlparams) return flag 一样的。很清楚了是吧? 6、接口层的建立 接口层很简单,就是工厂生产接口,D层实现接口,继承接口,让B层就可以直接调用工厂,工厂生产接口,让工厂决定实例化那个接口。这样看起来,好像是B层调用的是D层,而实际上是调用工厂,调用IDAL层。解除B层和D层的耦合。
这里我感觉很抱歉的是,上面用的是LoginDAL,接口层用的是IUser,这是不对的,一定要保持一致。
Imports Entity Public Interface IUser Function User_Login(ByVal user As Entity.LoginEntity) As System.Data.DataTable End Interface IWorklog : Public Interface IWorkLog Function SaveWorkLog(ByVal worklog As Entity.WorkLogEntity) As Boolean End Interface 下面我就要讲解B层是如何通过接口层调用D层的了。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- CodeSmith+SQLite+VS2010开发环境搭配
- Andorid Xml的写入与读取之PULL解析器
- ios – 当BLOC中的流值更改时导航到新屏幕
- c# – 使用ExpressionTree分配属性
- sprite-kit – 如何在Swift和SpriteKit中使用whiteColor
- React简介
- c# – 如何选择已使用OpenFileDialog打开的文件
- 深入理解vue $refs的基本用法
- Postgres psql: FATAL: Peer authentication failed for us
- Libcurl & Log4cplus 移植和使用 以及 Jsoncpp 简单使用