机房重构之七层登录

目录

  • 目录
  • 七层UML图
  • 七层具体展示
    • UI层
    • Facade层
    • BLL层
    • Factory层
    • IDAL层
    • DAL层
    • sqlHelper层
    • Entity实体
  • 遇到的问题
    • 往sqlHelper里传参数时用数组
    • 找不到指定文件
    • 自己的小想法
  • 结语

七层UML图

机房重构之七层登录_第1张图片

七层具体展示

机房重构之七层登录_第2张图片

UI层

Public Class frmLogin

    Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
        '输入不能为空
        If txtUserID.Text = "" Then
            MsgBox("请输入用户ID号", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            txtUserID.Focus()
        End If
        If txtPassWord.Text = "" Then
            MsgBox("请输入密码", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            txtPassWord.Focus()
        End If

        Try
            '实体获得窗体信息
            Dim user As New Entity.UserInfo
            Dim facade As New Facade.LoginFacade

            user.userID = txtUserID.Text.Trim()
            user.passWord = txtPassWord.Text.Trim()

            '将U层信息传入外观层
            Dim flag As Boolean
            Dim flagPSW As Boolean
            flag = facade.CheckUserID(user)
            'flagPSW = facade.CheckPassWord(user)

            '显示结果,先判断用户是否存在,存在再判断密码,密码正确则登录成功,否则提示密码错误
            If flag = False Then
                MsgBox("用户不存在,请重新输入", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                txtUserID.Text = ""
                txtPassWord.Text = ""
                txtUserID.Select()
                txtUserID.Focus()
            Else
                flagPSW = facade.CheckPassWord(user)

                If flagPSW = False Then
                    MsgBox("密码错误,请重新输入!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                    txtPassWord.Text = ""
                    txtPassWord.Select()
                    txtPassWord.Focus()
                Else
                    MsgBox("登录成功!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                    txtUserID.Text = ""
                    txtPassWord.Text = ""
                    Me.Hide()


                End If
            End If





        Catch ex As Exception
            MsgBox("未知错误")
        End Try
    End Sub
End Class

Facade层

Imports System.Reflection  '添加反射引用
Imports System.Configuration  '添加配置文件的引用
Imports System.Data
Imports IDAL

'反射+配置文件+抽象工厂实现数据访问


Public Class LoginFactory
    Private Shared ReadOnly AssemblyName As String = "DAL"  '数据程序集名称&命名空间DAL
    Dim strDB As String = System.Configuration.ConfigurationSettings.AppSettings("DB") '使用配置文件
    Public Function CreateIUser() As ILoginUser
        Dim classname As String = "DAL" + "." + strDB + "LoginDAL" '要实例化的D层类的名称
        Dim IUser As ILoginUser
        'CType函数将返回表达式显示的转换为指定数据类型、对象、结构、类或接口后的结果
        IUser = CType(Assembly.Load(AssemblyName).CreateInstance(classname), ILoginUser)
        Return IUser
    End Function


End Class

BLL层

Public Class LoginService
    Dim table As New DataTable
    Dim flag As Boolean
    Dim Factory As New Factory.LoginFactory
    Dim IUser As IDAL.ILoginUser
    Public Function CheckUserID(ByVal user As Entity.UserInfo) As Boolean
        IUser = Factory.CreateIUser() '调用工厂的CreateIUser方法创建IUser接口实例
        table = IUser.SelectUser(user)
        If table.Rows.Count = 0 Then
            flag = False
        Else
            flag = True
        End If
        Return flag
    End Function

    Public Function CheckPassWord(ByVal user As Entity.UserInfo) As Boolean
        '逻辑判断都在B 层做,U层只负责显示
        IUser = Factory.CreateIUser()
        table = IUser.SelectUser(user)
        If table.Rows(0).Item(2) = user.passWord Then
            flag = True
        Else
            flag = False
        End If
        Return flag

    End Function
End Class

Factory层

Imports System.Reflection  '添加反射引用
Imports System.Configuration  '添加配置文件的引用
Imports System.Data
Imports IDAL

'反射+配置文件+抽象工厂实现数据访问


Public Class LoginFactory
    Private Shared ReadOnly AssemblyName As String = "DAL"  '数据程序集名称&命名空间DAL
    Dim strDB As String = System.Configuration.ConfigurationSettings.AppSettings("DB") '使用配置文件
    Public Function CreateIUser() As ILoginUser
        Dim classname As String = "DAL" + "." + strDB + "LoginDAL" '要实例化的D层类的名称
        Dim IUser As ILoginUser
        'CType函数将返回表达式显示的转换为指定数据类型、对象、结构、类或接口后的结果
        IUser = CType(Assembly.Load(AssemblyName).CreateInstance(classname), ILoginUser)
        Return IUser
    End Function


End Class

IDAL层

Public Interface ILoginUser
    Function SelectUser(ByVal user As Entity.UserInfo) As DataTable

End Interface

DAL层

Imports System.Configuration
Imports IDAL
Imports System.Data.SqlClient
Public Class LoginDAL : Implements IDAL.ILoginUser
    Private SqlFavor As New SqlHelper.SqlFavor
    '判断用户名是否存在
    Public Function SelectUser(ByVal user As Entity.UserInfo) As DataTable Implements IDAL.ILoginUser.SelectUser
        Dim sql As String  '储存查询语句
        Dim table As DataTable
        '声明并实例化参数数组
        Dim paras As SqlParameter() = {New SqlParameter("@userID", user.userID), New SqlParameter("@passWord", user.passWord)}
        '数组 

        'sql = "select * from Users where ID = @userID and PassWord = @passWord"
        sql = "select * from Users where ID = @userID"
        '调用SQLHelper中的ExecSelect方法来查询,并获取返回值
        table = SqlFavor.ExecSelect(sql, CommandType.Text, paras)
        Return table
    End Function

End Class

sqlHelper层

Imports System.Data
Imports System.Data.SqlClient
Imports System.Configuration '配置文件的引用

Public Class SqlFavor
    '数据库连接
    Dim strConnection As String = "Server = jf; Database = Login; User ID = sa; PassWord = summer"
    Dim conn As New SqlConnection(strConnection)
    Dim cmd As New SqlCommand

    Public Function ExecSelect(ByVal cmdText As String, ByVal cmdType As CommandType, ByVal paras As SqlParameter()) As DataTable
        Dim sqlAdapter As SqlDataAdapter
        Dim dt As New DataTable
        Dim ds As New DataSet

        '给cmd 赋值
        cmd.CommandText = cmdText
        cmd.CommandType = cmdType
        cmd.Connection = conn
        cmd.Parameters.AddRange(paras) '添加参数

        sqlAdapter = New SqlDataAdapter(cmd) '实例化Adapter
        Try
            sqlAdapter.Fill(ds) '用adapter将dataset填充
            dt = ds.Tables(0) 'datatable是dataset的第一个表
            cmd.Parameters.Clear()  '清除参数

        Catch ex As Exception
            MsgBox("数据库操作")
        Finally
            Call CloseCmd(cmd) '关闭cmd命令
        End Try

        Return dt


    End Function

    Public Sub CloseCmd(ByVal cmd As SqlCommand)
        If Not IsNothing(cmd) Then '如果cmd存在
            cmd.Dispose() '销毁
            cmd = Nothing
        End If
    End Sub
End Class

Entity实体

Public Class UserInfo
    Private _userid As String
    Private _username As String
    Private _password As String
    Private _level As String

    Public Property userID As String
        Get
            Return _userid
        End Get
        Set(value As String)
            _userid = value
        End Set
    End Property

    Public Property userName As String
        Get
            Return _username 
        End Get
        Set(value As String)
            _username = value
        End Set
    End Property

    Public Property passWord As String
        Get
            Return _password
        End Get
        Set(value As String)
            _password = value
        End Set
    End Property

    Public Property level As String
        Get
            Return _level
        End Get
        Set(value As String)
            _level = value
        End Set
    End Property


End Class

遇到的问题

往sqlHelper里传参数时用数组

  Public Function ExecSelect(ByVal cmdText As String, ByVal cmdType As CommandType, ByVal paras As ***SqlParameter()***) As DataTable

之前三层时传参数是这样用的

 cmd.Parameters.Add(New SqlParameter("@ID", user.ID))
 cmd.Parameters.Add(New SqlParameter("@PassWord", user.PSW))

现在把DAL层里连接数据库和公共性的东西抽出来形成sqlHelper。所以要把D层中的sql,parameter等参数都传给sqlHelper,但是parameter中往往有好几个,所以就用到了数组。

找不到指定文件

机房重构之七层登录_第3张图片

反射的一个原则:一切皆以UI层的bin文件夹中的dll名称为中心。(原因很简单:.net类加载的机制就是默认从本程序集的bin文件中找,所以bin文件夹中一定要有要加载的程序集的dll)。UI层中bin文件夹中dll叫什么名字AssemblyPath就使用什么名字,bin内部类的全名叫什么,className就写成什么全名。.net中的引用:加入对某个程序集的引用就能在程序集有变化时自动拷贝dll。

以上摘自王雪娜的博客 机房重构七层登录之问题总结
总而言之,各层中的dll名称都以UI层的bin文件里的dLL名称为准,所以方法就是把D层属性里 生成 ——输出路径 改成UI层就OK了。

自己的小想法

我写七层的时候主要借鉴的是同学的博客,并做了一些小改动。同学的B层的返回值类型是datatable,然后在U层把窗体上的密码与table里的密码进行比较。感觉逻辑判断应该放在B层,就把这些判断都写到B层,然后B层和Facade层的返回值类型都是boolean。

在U层做判断的时候也做了一些小改动:写了一个嵌套的if语句来判断用户名和密码是不是正确,用户名正确但密码不正确就提示“密码错误”。试了试360 云盘遇到这种情况会给什么提示,它就是提示“密码错误”,感觉这样对用户比较方便。

结语

以前遇到错误心里就犯怵,不过还是在错误中收获最多。这次最欣慰的就是在巨人的肩膀上加上了自己的想法,虽然都是一些简单的想法,但是完全自己设计创造一个东西都是要这样慢慢成长的。不要想太多,像老师说的,做吧,做着做着可能就理解了。在这样的精神指导下,我就要开始机房重构了。

你可能感兴趣的:(【项目实践】)