前言
三层的学习结束了一段时间了,但是对于三层的理解总感觉差点什么东西,有时候眼界也比较局限,总在自己的小圈子里面打转转。
自上次师父验收项目之后,我开始尝试着看一些其他人的代码,试着从不同的代码中找寻自己新的方向及灵感。
内容
解耦
前段时间,正巧在厕所碰到了雷哥,希望能从雷哥嘴中套出点东西来,最后抛出了两个问题。
为什么要用三层?
深受米老师的熏陶,当然是为了解耦。
那为什么三层能够解耦?
。。。因为。。。那个。。。
这略带理论性的东西,一下子把我给难倒了。
看了一些材料,还是没有找到我想要的答案。这应该是非常基础的东西。
回想到了第一次的机房收费系统,好像找到了写眉目。
第一次机房:
代码全都写在窗体中,顶多会用个模块,而为什么用,如何更好的使用,并不了解。
机房重构:
知道了类库的存在,而正好相反的是窗体中的代码是很少的。
第一次机房:
正向上面说的,代码全都堆在窗体中,修改某个功能非常的困难,无从下手,通常想要修改一个地方,好多地方都要修正
机房重构:
虽然还没有写入很多的功能,但就目前写的这两个功能看,逻辑判断处理等都条理清晰,便于抽离修改
第一次机房:
同样,代码冗余过大也是因为上面的问题造成的,虽然能提炼部分方法,但仍是杯水车薪。
机房重构:
因为分层的关系,同样的问题可以提炼出来供需要时调用,减少代码的冗余
传实体
在刚用C#敲三层例子的时候,我最疑惑的一个地方就是,在层与层之间调用时,调用的下一层(比如:U层调用B层的方法,我自己通俗的理解为B层是U层的下一层)的方法,它的返回值类型为什么是实体层类?因为这个问题在转成VB.NET的时候我都进行不下去了。
直到我看了一个同学的代码我就更蒙圈了,为什么他的方法参数和返回值都要是实体层类?
这也影响了不少时间,再接着我就不管不顾,任凭感觉自己乱敲一气,发现原来用于层与层之间调用的那个方法,它的返回值和参数都可以不是实体层对象,并且我同样完成了登录。
这,不仅没有使我高兴,而使我更加搞不懂了,他们问什么要用实体呢?头都要大了。
问题还是没有解决,虽然也查了资料,但是我选择先放一放,接着向下一个功能进发。
我打算先弄一个注册卡号的功能,我就发现,原来将实体当参数是多么自然的一个过程。
我发现,如果不用实体(在实体层的一个类,里面都是一些属性,基本对应于数据库中的表)的话,一个一个传变量的话要好多,非常麻烦,而返回值嘛,我发现原来完全不需要是实体。
并且,最好不要是实体,因为实体是从上一层传到的下一层,到最后一层给实体赋值的时候,从上一层很容易就能得到了实体的数据,也并不需要RETURN。
就这一很简单的问题,还困扰我好长时间,并且还是在一个机缘巧合的情况下了解到的。
到了这,这三层之间的调用关系,我才算有了一个基本的了解。
代码展示
我想展示的并不是一个利用实体完成的看起来非常不错的一篇代码。
我想给大家看的正是我没有利用实体而完成的登录,不要问我为什么。
我的文章我做主。任性。
下面的代码还有不严谨和欠妥之处,还望多多斧正。
U层代码
<span style="font-size:18px;">Imports BLL REM 添加B层引用
Private Sub btnLogin_Click(sender As Object, e As EventArgs) Handles btnLogin.Click
Dim strUserID As String = txtUserID.Text.Trim REM 定义字符串变量用于存储用户ID并赋值
Dim strPassWord As String = txtPassWork.Text REM 定义字符串变量用于存储密码并赋值
Dim log As New LoginBll REM 实例化一个B层对象
txtPrompt.Text = log.Test(strUserID, strPassWord) REM 调用B层对象的方法,返回值给窗体上的一个文本框,用于提示
If txtPrompt.Text = "" Then
Me.Hide()
frmMain.Show()
End If
End Sub</span>
B层代码
Imports DAL REM 添加D层引用
Public Function Test(strUserID As String, strPassWord As String) As String
REM 省略部分逻辑判断
If strUserID = "" Then
Return "用户名不能为空"
End If
If strPassWord = "" Then
Return "密码不能为空"
End If
Dim log As New LoginDal REM 实例化D层对象
Return log.selectUser(strUserID, strPassWord) REM 调用D层对象的方法
End Function
Imports System.Data
Imports System.Data.SqlClient
Public Function selectUser(strUserID As String, strPassWrod As String) As String
Dim conn As New SqlConnection(DbUtil.connstring)
REM SqlConnection 表示一个到SqlServer数据库打开的连接
Dim sql As String = "select * from user_info where userid='" & strUserID & "' and password = '" & strPassWrod & "'"
REM sql 表示对数据库进行操作的字符串
Dim cmd As New SqlCommand(sql, conn)
REM 表示对数据库进行操作,
Dim Temp As String = ""
REM 一个临时使用的字符串变量
conn.Open()
REM 打开数据库连接
Dim Reader As SqlDataReader
REM SqlDataReader提供一种从SqlServer数据库读取行的只进流的方式
Reader = cmd.ExecuteReader
REM 若要创建,必须调用SqlCommand对象的ExecuteReader方法。
REM 便于个人理解,我将它理解成第一次机房时的数据记录集对象,像数组或者集合
Reader.Read()
REM 读取数据
Try
Temp = Reader.GetInt32(0).ToString REM 读取数据集中的第一条数据
Return ""
Catch ex As Exception
Return "用户名或密码错误"
End Try
End Function
Public Class DbUtil
Public Shared Function connstring() As String
connstring = "Server= DESKTOP-E07CTB9; database=ComputerRoom Charging System; User Id =sa;Password=1"
End Function
End Class
总结
成长总是一步一步的,爱你总是无时不在的。