• .NET分层登陆——机房收费系统再总结


        去年的时候,我写过一篇机房收费系统登陆的总结文章,那是站在VB的基础上,直接查询数据库实现的登陆。是很初期的知识。如果想了解详情,请看VB查询数据库之登陆窗体——机房收费系统总结(一)

        今天,我要换一个角度,换一个方式,来实现登陆。首先,我选择的开发工具是VB.NET,数据库是SQLSever2008。其次,我用的是三层的思想,把界面,逻辑和数据都分开,减少相互之间的影响。在次,界面层尽量简洁,所有的算法和业务逻辑都写到逻辑层,同时使用了接口和工厂模式以及外观模式,减少了相互之间的依赖,降低了耦合。最后,通过文档和UML图,写出代码,实现登陆。

        首先,看看我设计的登陆时序图(如有错误,欢迎指出,不胜感激):


        看到图之后,如果你拥有一定的经验,相信对你来说,代码就不是问题了吧。下面,我把我的代码放在下面,仅供参考哦!(对了,U层界面没有变,如果想知道,请看连接博客)。

        首先是实体层代码:

        用户实体层:

    Public Class UserInfo
        Private _userid As String
        Private _password As String
        
        Public Property UserID As String
            Get
                Return _userid
            End Get
            Set(value As String)
                _userid = value
    
            End Set
        End Property
    
        Public Property PassWord As String
            Get
                Return _password
            End Get
            Set(ByVal value As String)
                _password = value
            End Set
        End Property
    
       End Class

    
        工作表实体层:
    

    <span style="font-size:18px;">Imports System
    Imports System.Data
    
    
    ''' <summary>
    ''' 数据库表OpeLineRecord所对应的实体类
    ''' </summary>
    Public Class OpeLineRecordEntity
    
        Private m_Opercomprecordid As String
        Private m_Operatorid As String
        Private m_Landdate As String
        Private m_Landtime As String
        Private m_Outdate As String
        Private m_Outtime As String
        Private m_Status As String
        Private m_Computerid As String
    
    
    
        Public Sub OpeLineRecordEntity()
            m_Opercomprecordid = ""
            m_Operatorid = ""
            m_Landdate = ""
            m_Landtime = ""
            m_Outdate = ""
            m_Outtime = ""
    
            m_Status = ""
            m_Computerid = ""
    
        End Sub
        ''' <summary>
        '''设置或返回值Opercomprecordid
        ''' </summary>
        Public Property Opercomprecordid As String
            Get
                Return m_Opercomprecordid
            End Get
            Set(value As String)
                m_Opercomprecordid = value
            End Set
        End Property
    
        ''' <summary>
        '''设置或返回值Operatorid
        ''' </summary>
        Public Property Operatorid As String
            Get
                Return m_Operatorid
            End Get
            Set(value As String)
                m_Operatorid = value
            End Set
        End Property
    
        ''' <summary>
        '''设置或返回值Landdate
        ''' </summary>
        Public Property Landdate As String
            Get
                Return m_Landdate
            End Get
            Set(value As String)
                m_Landdate = value
            End Set
        End Property
    
        ''' <summary>
        '''设置或返回值Landtime
        ''' </summary>
        Public Property Landtime As String
            Get
                Return m_Landtime
            End Get
            Set(value As String)
                m_Landtime = value
            End Set
        End Property
    
        ''' <summary>
        '''设置或返回值Outdate
        ''' </summary>
        Public Property Outdate As String
            Get
                Return m_Outdate
            End Get
            Set(value As String)
                m_Outdate = value
            End Set
        End Property
    
        ''' <summary>
        '''设置或返回值Outtime
        ''' </summary>
        Public Property Outtime As String
            Get
                Return m_Outtime
            End Get
            Set(value As String)
                m_Outtime = value
            End Set
        End Property
    
    
        ''' <summary>
        '''设置或返回值Status
        ''' </summary>
        Public Property Status As String
            Get
                Return m_Status
            End Get
            Set(value As String)
                m_Status = value
            End Set
        End Property
    
        ''' <summary>
        '''设置或返回值Computerid
        ''' </summary>
        Public Property Computerid As String
            Get
                Return m_Computerid
            End Get
            Set(value As String)
                m_Computerid = value
            End Set
        End Property
    
    End Class</span>
        将Datatable转换为泛型

    <span style="font-size:18px;">Imports System.Collections.Generic    '增加泛型的命名空间
    Imports System.Reflection
    Public Class EntityHelper
        Public Shared Function convertTolist(Of T As {New})(ByVal dt As DataTable) As IList(Of T)  '将DataTable转化为泛型集合
    
            '注意:1,convertToList(Of T As {New} 这里的New是用来约束T的,必须有,不然new T 的时候会出现错误
            ''2,new约束在C#和VB.NET里面的写法是不一样的,C#里面用的是where来为T加上约束的  
    
            Dim myList As New List(Of T) '定义最终返回的集合
    
            Dim myType As Type = GetType(T)   '得到实体类的类型么
            Dim dr As DataRow   '定义行集
    
            Dim tempName As String = String.Empty   '定义一个临时变量
    
            '遍历DataTable的所有数据行
            For Each dr In dt.Rows
    
                Dim myT As New T   '定义一个实体类的对象
                Dim propertys() As PropertyInfo = myT.GetType().GetProperties()  '定义属性集合
                Dim Pr As PropertyInfo
    
                '遍历该对象的所有属性
                For Each Pr In propertys
                    tempName = Pr.Name   '将属性名称赋值给临时变量
    
                    '检查DataTable是否包含此列(列名==对象的属性名)
                    If (dt.Columns.Contains(tempName)) Then   '将此属性与DataTable里的列名比较,查看DataTable是否包含此属性
    
                        '判断此属性是否有Setter
                        If (Pr.CanWrite = False) Then  '判断此属性是否可写,如果不可写,跳出本次循环
                            Continue For
                        End If
    
                        Dim value As Object = dr(tempName)     '定义一个对象型的变量来保存列的值
    
                        If (value.ToString <> DBNull.Value.ToString()) Then '如果非空,则赋给对象的属性
                            Pr.SetValue(myT, value, Nothing)    '在运行期间,通过反射,动态的访问一个对象的属性
                        End If
                    End If
                Next
    
                myList.Add(myT)  '添加到集合
            Next
    
            Return myList   '返回实体集合
        End Function
    End Class
    </span>

         然后是接口层IDAL:

    <span style="font-size:18px;">Public Interface IUser
        Function SelectUser(ByVal user As entity.UserInfo) As List(Of UserInfo)
      
    End Interface</span>
        D层:

    <span style="font-size:18px;">Imports IDAL
    Imports entity
    Imports System.Data.SqlClient
    Public Class UserDAL : Implements IDAL.IUser
    
    
    
    
        Public Function SelectUser(user As UserInfo) As List(Of UserInfo) Implements IUser.SelectUser
            Dim strUserID As String = user.UserID
            Dim helper As New Helper.Sqlhelper
            Dim dt As New DataTable
            Dim mylist As List(Of UserInfo)
    
            Dim strSql As String = "select * from OperatorInfo where OperatorID=@UserID and state='使用'"
            Dim sqlParams As SqlParameter() = {New SqlParameter("@UserID", strUserID)} '声明并实例化参数
            dt = helper.ExecuteNonQuery(strSql, CommandType.Text, sqlParams)  '调用SqlHelper类中的ExecSelect()方法来执行查询,并获取返回值
            mylist = EntityHelper.convertTolist(Of UserInfo)(dt)           '将dt转换为泛型集合
    
            Return mylist
        End Function
      
    
       
        End Function
    End Class
    </span>

        

        增加记录

    <span style="font-size:18px;">Imports IDAL
    Imports entity
    Imports System.Data.SqlClient
    Public Class UserWorklogDAL : Implements IDAL.IUserWorklog
    
    
        Public Function AddUserworklog(worklog As OpeLineRecordEntity) As Boolean Implements IUserWorklog.AddUserworklog
            '声明一个SqlHelper类型的helper
            Dim helper As New Helper.Sqlhelper
            Dim dt As New Integer
            '声明并实例化需要执行的SQL语句
            Dim strSql As String = "Insert into OpeLineRecord (OperatorID,landDate,landTime,ComputerID,Status) values (@OperatorID,@landDate,@landTime,@ComputerID,@Status)"
    
            '声明兵实例化参数数组
            Dim sqlParams As SqlParameter() = {New SqlParameter("@OperatorID", worklog.Operatorid),
                                              New SqlParameter("@LandDate", worklog.Landdate),
                                               New SqlParameter("@LandTime", worklog.Landtime),
                                               New SqlParameter("@ComputerID", worklog.Computerid),
                                               New SqlParameter("@Status", worklog.Status)}
    
            '调用SqlHelper类中的ExecAddDeleteUser()方法来执行添加信息,获取返回值并Return
            dt = helper.ExecAddDelUpdate(strSql, CommandType.Text, sqlParams)
            Return dt
            If dt > 0 Then
                Return True
            Else
                Return False
            End If
    
        End Function</span>

    外观:

    <span style="font-size:18px;">Public Class LoginFAC
        Public Function Login(ByVal user As entity.UserInfo) As String
    
            Dim userlogin As New BLL.UserManager
            userlogin.IsUserExit(user)
    
            If Not userlogin.IsUserExit(user) Then
                Throw New Exception("密码不正确")
    
            End If
    
    
            userlogin.CheckPWDIsRight(user)
            If userlogin.CheckPWDIsRight(user) = False Then
                Throw New Exception("密码不正确")
            End If
    
            '判断用户是否登录了系统
            Dim userwork As New entity.OpeLineRecordEntity
            Dim workbll As New BLL.UserWorklogManager
            userwork.Operatorid = user.UserID
            userwork.Landdate = DateTime.Now.ToString("yyyy/MM/dd")
            userwork.Landtime = DateTime.Now.ToString("HH:mm")
            userwork.Computerid = System.Net.Dns.GetHostName()
            userwork.Status = "正在值班"
    
            '添加登录信息
            workbll.AddWorklog(userwork)
    
    
        End Function
    End Class</span>

       

         SQLhelper层:

    <span style="font-size:18px;">'通过配置文件获取连接字符串
    Imports System.Data
    Imports System.Data.SqlClient
    'Imports System.Configuration   '添加对配置文件的引用
    
    Public Class Sqlhelper
    
        '调用配置文件  
        Private ReadOnly strConnection As String = Configuration.ConfigurationManager.AppSettings("ConnStr").ToString
    
        '有参数的查询
        'return DataTable 查询出的表格
        Public Function ExecuteNonQuery(ByVal cmdText As String, ByVal cmdType As CommandType, ByVal sqlParams As SqlParameter()) As DataTable
            Using conn As New SqlConnection(strConnection)   '使用连接池,可以在使用完成后自动关闭连接
                Dim cmd As SqlCommand = conn.CreateCommand() '
                Dim adp As SqlDataAdapter
                Dim ds As New DataSet
                cmd.CommandText = cmdText  '需要执行的SQL语句
                cmd.CommandType = cmdType '给出Sql语句的类型
                cmd.Parameters.AddRange(sqlParams) '参数数组,参数个数根据实际情况而定
                adp = New SqlDataAdapter(cmd)
                Try
                    conn.Open()
                    adp.Fill(ds)
                    'Return cmd.ExecuteNonQuery()
                    Return ds.Tables(0)
                Catch ex As Exception
                    Return Nothing
                    Throw ex
                End Try
            End Using
        End Function
    
    
        '有参数的增删改
        Public Function ExecAddDelUpdate(ByVal cmdText As String, ByVal cmdType As CommandType, ByVal sqlParams As SqlParameter()) As Integer
            Using conn As New SqlConnection(strConnection)
                Dim cmd As SqlCommand = conn.CreateCommand()
                Dim adp As SqlDataAdapter
                Dim ds As New DataSet
                cmd.CommandText = cmdText
                cmd.CommandType = cmdType
                cmd.Parameters.AddRange(sqlParams)
                adp = New SqlDataAdapter(cmd)
                Try
                    conn.Open()
                    adp.Fill(ds)
                    Return ds.Tables.Count
                Catch ex As Exception
                    Return Nothing
                    Throw ex
                End Try
            End Using
        End Function
    
    End Class
    </span>

        工厂层:

    <span style="font-size:18px;">Imports System.Reflection
    Imports [IDAL]
    Public Class BDFactory
        'Private Shared ReadOnly db As String = Configuration.ConfigurationManager.AppSettings("DBString")
        'Private Shared ReadOnly assemblyName = db + "DAL"
        Private Shared ReadOnly assemblyName = "SQLDAL"
    
        Public Function CreateUserDAO() As IDAL.IUser
    
            'Dim className As String = assemblyName + "." + db + "UserDAL"
            Dim className As String = assemblyName + "." + "UserDAL"
            Return CType(Assembly.Load(assemblyName).CreateInstance(className), IUser)   '返回IUser
    
        End Function   </span>

    <span style="font-size:18px;">Public Function CreateUserworklogDAO() As IDAL.IUserWorklog
            Dim strInstance As String = assemblyName + "." + "UserWorklogDAL"     '所要实例化的对象(程序集与命名空间同名)  
            Return CType(Assembly.Load(assemblyName).CreateInstance(strInstance), IUserWorklog)   '返回IUserWorklog
        End Function</span>

    B层:

        添加上机记录

    <span style="font-size:18px;">Imports Factory
    Imports entity
    
    Public Class UserWorklogManager
        Private ReadOnly factory As Factory.BDFactory = New Factory.BDFactory
        Dim iu As IDAL.IUserWorklog    '声明并实例化变量iuser为:调用factory.CreateUserDAO()方法所返回来的IUser
    
        '添加用户工作记录
        Public Function AddWorklog(ByVal worklog As entity.OpeLineRecordEntity) As Boolean
            iu = factory.CreateUserworklogDAO()
            Dim dt As Integer
            dt = iu.AddUserworklog(worklog)
    
            If dt > 0 Then
                Return True
            Else
                Return False
            End If
        End Function
    </span>
         查询用户是否存在 密码是否正确

    <span style="font-size:18px;">Imports entity
    Public Class UserManager
        Private ReadOnly factory As Factory.BDFactory = New Factory.BDFactory()
        Dim iuser As IDAL.IUser
    
        Public Function IsUserExit(ByVal user As entity.UserInfo) As Boolean
            Dim iu As IDAL.IUser
            Dim mylist As List(Of UserInfo)
    
            iu = factory.CreateUserDAO()
            mylist = iu.SelectUser(user)
    
            If mylist.Count = 0 Then
                Return False
            Else
                Return True
            End If
    
        End Function
        
        Public Function CheckPWDIsRight(ByVal user As entity.UserInfo) As Boolean
            Dim iu As IDAL.IUser
            Dim mylist As List(Of UserInfo)
            iu = factory.CreateUserDAO()
            mylist = iu.SelectUser(user)
    
            If Trim(mylist(0).PassWord) <> user.PassWord Then
                Throw New Exception("输入密码不正确")
                Return False
            Else
                Return True
            End If
        End Function</span>
    最后是U层

    <span style="font-size:18px;">Public Class frmlogin
    
        Private Sub BtnOK_Click(sender As Object, e As EventArgs) Handles BtnOK.Click
            Dim user As New entity.UserInfo '实例化User
            user.UserID = txtUserName.Text
            user.PassWord = txtPassword.Text
            If txtUserName.Text.Trim().Length > 20 Then
                MessageBox.Show("不能超过20位数字", "提示")
                Exit Sub
            End If
            If txtUserName.Text.Trim() = "" Then
                MessageBox.Show("请输入用户名", "提示", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                Exit Sub
            ElseIf txtPassword.Text.Trim() = "" Then
                MessageBox.Show("请输入用密码", "提示", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                Exit Sub
            End If
            Try
                '调用外观
                Dim loginfac As Facade.LoginFAC = New Facade.LoginFAC()
                loginfac.Login(user)
                Me.Hide()
    
                ForMain.Show()
            Catch ex As Exception
               MsgBox(ex.Message, CType(vbOKOnly + MsgBoxStyle.Information, MsgBoxStyle), "提示")
            End Try
    
        End Sub
    
        
    End Class
    </span>
       Ok 系统结束,可能会有轻微的问题,细心就一定会解决(因为在粘贴的过程中,可能一不留神,你懂得……),相对第一次来说,代码和逻辑上,并没有简单,而且反倒难了,那我们为什么还有继续呢?

        不知道读者是否有这样的疑问。其实,很简单,虽然代码和逻辑麻烦了,但是系统的性能更好了,逻辑也更清楚了,同时,减少了U层的负担,工作具体化。同样,兼容性扩展性更好了,健壮性也有所提高。更加适合合作开发。这是一个小系统,如果是大系统,是不是优势就会更明显呢!

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    CF1578M The Mind
    NWERC 2019 Kitesurfing
    Currency Editorial
    [省选联考 2021 A 卷] 支配
    【LGR101】洛谷 2 月月赛 I & WdOI R1.5 / RdOI R3.5 Div.2 C [旅人 1977] 题解
    CF1648D Serious Business
    jdk环境变量配置
    html,css jq,js关于多行,单行文字内容溢出用点点点(...)省略号表示
    用js动态改变css样式表
    css 的 ellipsis 实现超出的数字用省略号表示
  • 原文地址:https://www.cnblogs.com/lucari/p/4608565.html
Copyright © 2020-2023  润新知