在上一篇博客中的开篇就介绍了实体的作用,但是上一篇中的用C#敲的那个三层登录的小例子中并没有用实体作为参数来传递,因为小例子中的参数很少就两三个,刚刚接触三层就为了练习三层的思想就没有用实体来穿参,昨天在对登录这条线敲通了只后,就琢磨当参数多的时候呢(像我们机房收费系统中,注册,上下机等),于是开始用实体作为参数并且用VB.NET重新敲了一遍。
在第二遍的时候我就把其中的分数和用户信息封装到了一个实体当中来传参数,等敲完后,发现有数据冗余,因为在传送用户信息的时候没有用到分数,这样就有很多数据在浪费,如果数据量大的时候就造成效率低下。
所以我就重新修改我的思路,将分数和用户信息分开分别封装成不同的实体,这样就可以避免数据在传送中的浪费,下面类分析一下我的第三版的代码:
首先看一下我的解决方案:
实体层代码:
<span style="font-size:24px;">Public Class UserInfo
Dim _username As String
Dim _password As String
Dim _email As String
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 Exmail() As String
Get
Return _email
End Get
Set(value As String)
_email = value
End Set
End Property
End Class
</span>
<span style="font-size:24px;"></span><pre name="code" class="vb">Public Class Scores
Dim _score As String
Public Property Scores() As String
Get
Return _score
End Get
Set(value As String)
_score = value
End Set
End Property
End Class
在实体层主要封装两个实体,避免我们在过程中参数个数过多造成混乱或者遗忘等。
U层代码:
Public Class Form1
Private Sub btOk_Click(sender As Object, e As EventArgs) Handles btOk.Click
Dim manager As BLL.LoginManager = New BLL.LoginManager()
Dim user As Model.UserInfo = New Model.UserInfo()
user.UserName = txtUserName.Text '通过文本框给User实体赋值
user.Password = txtPassword.Text
manager.UserLogin(user) 'user作为实体参数传给B层
MessageBox.Show("成功登录:" + user.UserName)
End Sub
End Class
U层的功能比较好理解,主要是和用户交互,从用户读入数据,传给B层进行处理,等到有了处理后在展示给用户。
在这里我们的参数不在是单个的变量而是user这个实体,只有这么一个参数,使我们的代码更加清晰,同时这里没有用到”分数“这个数据,如果封装在一起的话就会被传送,降低效率。
B层代码:
Public Class LoginManager
Public Function UserLogin(ByVal user As Model.UserInfo) As Model.UserInfo
Dim userD As DAL.UserDAO = New DAL.UserDAO()
Dim Uuser As Model.UserInfo = New Model.UserInfo()
Dim score As Model.Scores = New Model.Scores()
Uuser = userD.SelectUser(user) 'user作为实体传给D层,但是Uuser中还没有值(正向)
'Uuser变量是从数据库中查询完毕后从D层传回来的数据
If (Not IsDBNull(Uuser)) Then
score.Scores = 20 '给score变量的Scores属性赋值
Dim sc As DAL.ScoreDAO = New DAL.ScoreDAO()
sc.UpdateScore(Uuser, score) '将两个实体作为参数再次传给D层
Else
Throw New Exception("登录失败")
End If
Return Uuser
End Function
End Class
B层业务逻辑层主要是进行逻辑判断的,不关心传进什么样的变量,不管数据库中是怎样查询数据的,只是根据需求进行必要的逻辑判断。
上面的UserLogin()方法接收了从B层传过来的User实体参数,并且将User实体接着通过调用D层的SelectUser()方法传给D层。并且进行完逻辑判断后将Uuser作为参数穿给U层。
在我们调用D层的UpdateScore()方法的时候,我们发现这里用到了score这个数据,所以我们只在这里用到了Score这个实体作为参数传递。
D层代码:
Imports System.Data.SqlClient
Public Class DbUtil
Public Shared Function ConnString() As SqlConnection
Dim cnStr As String = "Server =晓;DataBase =Login;User ID=sa;Password=123456"
Dim cn As SqlConnection = New SqlConnection(cnStr)
Return cn
End Function
End Class
</pre><pre name="code" class="vb">Imports System.Data.SqlClient
Public Class ScoreDAO
Public Sub UpdateScore(ByVal user As Model.UserInfo, ByVal score As Model.Scores)
Dim cn As SqlConnection = DbUtil.ConnString() '连接数据库
Dim sql As String = "INSERT INTO SCORES(UserName,Score) Values(@UserName,@Score)"
Dim cmd As SqlCommand = New SqlCommand(sql, cn) '执行SQL语句
'给占位符赋值
cmd.Parameters.Add(New SqlParameter("@UserName", user.UserName))
cmd.Parameters.Add(New SqlParameter("@Score", score.Scores))
cn.Open() '打开数据库
cmd.ExecuteNonQuery()
End Sub
End Class
Imports System.Data.SqlClient
Public Class UserDAO
Public Function SelectUser(ByVal user As Model.UserInfo) As Model.UserInfo
Dim cn As SqlConnection = DbUtil.ConnString()
Dim sql As String = "SELECT ID,UserName,Password,Email FROM USERS WHERE UserName =@UserName AND Password = @Password"
Dim cmd As SqlCommand = New SqlCommand(sql, cn)
cmd.Parameters.Add(New SqlParameter("@UserName", user.UserName))
cmd.Parameters.Add(New SqlParameter("@Password", user.Password))
cn.Open()
Dim reader As SqlDataReader = cmd.ExecuteReader()
Dim Buser As Model.UserInfo = New Model.UserInfo() '实例化Buser往B层传参
While (reader.Read())
Buser.UserName = reader.GetString(1)
Buser.Password = reader.GetString(2)
End While
Return Buser
End Function
End Class
D层负责和数据库交互,对数据库的增、删、改、查等操作,这里需要我们熟悉VB.NET 中和数据库交互的语句,执行完成后会把数据传给B层。
小结
从上面我们可以看出,每层都有自己的特有的功能,不想我们在VB6.0版机房中那样没有一个窗体中都会有很多的复杂的操作,彼此的耦合性很大,很难扩展。在参数方面有效的避免了参数的混乱局面,大家可以想象一下,我们当时对机房是多少个变量啊,如果用实体则可以是代码更加清晰。
如果代码有不妥的地方,还望敬爱的读者留言指出!