.NET分層登陸——機房收費系統再總結,.net收費系統
去年的時候,我寫過一篇機房收費系統登陸的總結文章,那是站在VB的基礎上,直接查詢資料庫實現的登陸。是很初期的知識。如果想瞭解詳情,請看VB查詢資料庫之登陸表單——機房收費系統總結(一)。
今天,我要換一個角度,換一個方式,來實現登陸。首先,我選擇的開發工具是VB.NET,資料庫是SQLSever2008。其次,我用的是三層的思想,把介面,邏輯和資料都分開,減少相互之間的影響。在次,介面層盡量簡潔,所有的演算法和商務邏輯都寫到邏輯層,同時使用了介面和原廠模式以及面板模式,減少了相互之間的依賴,降低了耦合。最後,通過文檔和UML圖,寫出代碼,實現登陸。
首先,看看我設計的登陸時序圖(如有錯誤,歡迎指出,不勝感激):
看到圖之後,如果你擁有一定的經驗,相信對你來說,代碼就不是問題了吧。下面,我把My Code放在下面,僅供參考哦!(對了,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 SystemImports 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 PropertyEnd Class</span>
將Datatable轉換為泛型
<span style="font-size:18px;">Imports System.Collections.Generic '增加泛型的命名空間Imports System.ReflectionPublic 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 FunctionEnd 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 IDALImports entityImports System.Data.SqlClientPublic 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 FunctionEnd Class</span>
增加記錄
<span style="font-size:18px;">Imports IDALImports entityImports System.Data.SqlClientPublic 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 FunctionEnd Class</span>
SQLhelper層:
<span style="font-size:18px;">'通過設定檔擷取連接字串Imports System.DataImports 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 FunctionEnd Class</span>
工廠層:
<span style="font-size:18px;">Imports System.ReflectionImports [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 FactoryImports entityPublic 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 entityPublic 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層的負擔,工作具體化。同樣,相容性擴充性更好了,健壯性也有所提高。更加適合合作開發。這是一個小系統,如果是大系統,是不是優勢就會更明顯呢!
網路考試系統安全最佳化例如同一個機房內,怎使電腦間不可以檔案夾共用怎通過net程式更改註冊表
你把電腦來賓使用者(GUEST)關了就可以。我的電腦右鍵.管理.本機使用者名和組.使用者名稱Guest。再右鍵屬性,帳戶已停打勾就行了。別人就看不到了。
Aspnet網站發布在虛擬機器主機上後,出現問題: 不可以識別的屬性“targetFramework”注意屬性名稱區分大小
空間商的空間如果支援 .net版本切換的話,你直接登陸空間管理面板,去切換下 .net版本就可以了,但是一般空間只支援 .net2.0,.net3.0,.net3.5 ,如果你空間後台無法切換到.net4.0版本的話,你需要去問下你的空間商空間支援不支援4.0版本,自己無法切換,只能讓你空間商給調整下,如果調整不了的話,這個空間你就不能用了。
參考資料:萬網互聯--69dns竭誠為您解答!