問題背景:
原先做機(jī)房收費(fèi)系統(tǒng)的時(shí)候,對于D層訪問數(shù)據(jù)庫,對數(shù)據(jù)庫的操作基本上都是通過SQL語句實(shí)現(xiàn)的,這樣導(dǎo)致的一個(gè)問題就是在完成機(jī)房收費(fèi)系統(tǒng)中,產(chǎn)生了一些容易被忽略的邏輯黑洞。例如:在退卡業(yè)務(wù)邏輯中,要判斷從注冊表中是否刪除成功,其次,還要判斷是否將退卡記錄添加到退卡記錄表中,兩者都成功之后,標(biāo)識退卡業(yè)務(wù)邏輯完成,任何一個(gè)失敗,退卡業(yè)務(wù)邏輯標(biāo)識失敗。我原先的思路有點(diǎn)片面化,就是通過and連接符來判斷兩者是否都為true:
If ICancelcard.AddCancelCard(EntityCancelCard) = True And IStuInfo.DeleteStudent(EntityCancelCard) = True Then Return True Else Return False End If |
但是這樣就出現(xiàn)了一個(gè)思維漏洞:假設(shè)一種情況——從卡的注冊表中刪除成功了,但是添加信息的時(shí)候卻添加失敗了,按照上述代碼,則會給用戶提示:用戶退卡失敗。但是這時(shí)候卻已經(jīng)從卡的注冊表中刪除的情況;
解決方式(一):——存儲過程
存儲過程:
是一組為了完成特定功能的SQL 語句集,經(jīng)編譯后存儲在數(shù)據(jù)庫中,用戶通過指定存儲過程的名字并給出參數(shù)(如果該存儲過程帶有參數(shù))來執(zhí)行它。對于上述的問題,用存儲過程來解決:當(dāng)從卡注冊表中刪除某個(gè)卡的時(shí)候,將卡的信息添加到退卡記錄表中:
CREATEPROCEDURE Pro_CancelCard @StudentIDchar(10), @CardIDint, @CancelCashnumeric(18,2), @Datechar(20), @TimeChar(20), @UserIDChar(10), @StatusChar(10), AS BEGIN deletefrom TB_Student_Info whereCardID=@CardID SETNOCOUNT ON; insert TB_CancelCard_Infovalues(@StudentID,@CardID,@CancelCash,@Date,@Time,@UserID,@Status) END GO |
解決方式(二):——事務(wù)結(jié)合存儲過程
事務(wù):
是指作為單個(gè)邏輯工作單元執(zhí)行的一系列操作。事務(wù)處理可以確保除非事務(wù)性單元內(nèi)的所有操作都成功完成,否則不會永久更新面向數(shù)據(jù)的資源。用我們通俗的理解,就是武俠小說中的:不成功,便成仁!要不都成功,要不都不成功。其最重要的特征就是一致性,也可以理解為原子性
Create procedure [dbo].[PROC_UpStuCash] @StudentID char(10), @CardID int, @CancelCash numeric(18,2), @Date char(20), @Time Char(20), @UserID Char(10), @Status Char(10), as begin set nocount on; set xact_abort on ; /開始事務(wù) begin tran delete from TB_Student_Info where CardID =@CardID insert TB_CancelCard_Info values(@StudentID,@CardID,@CancelCash,@Date,@Time,@UserID,@Status) if @@ERROR = 0 commit tran /都執(zhí)行成功,提交事務(wù) else rollback tran /任何一個(gè)失敗,事務(wù)回滾 end |
在D層的實(shí)現(xiàn):
''' 刪除注冊用戶學(xué)生 '''</summary> ''' <param name="Student"></param> ''' <returns>Boolean</returns> ''' <remarks>如果刪除成功,返回ture 否則返回false</remarks> Public Function DeleteStudent(Student As CancelCardEntity) As Boolean Implements IStudentInfo.DeleteStudent Dim paras As SqlParameter() Try paras = New SqlParameter() { New SqlParameter("@CardID", Student.CancelCardID), New SqlParameter("@StudentID", Student.CancelStuID), New SqlParameter("@CancelCash", Student.CancelCash), New SqlParameter("@Date", Student.CancelDate), New SqlParameter("@Time", Student.CancelTime), New SqlParameter("@UserID", Student.CancelUserID), New SqlParameter("@Status", "結(jié)賬") } sqlStr = "Pro_CancelCard" Return SqlHelperDAL.Instance.ExecAddDelUpdate(sqlStr, CommandType.StoredProcedure, paras) Catch ex As Exception Throw ex End Try End Function |
小結(jié):
對于數(shù)據(jù)庫完整性,由原先的一無所知,到初步了解,以及到現(xiàn)在的慢慢的使用,這是一個(gè)慢慢的過程;當(dāng)然,事務(wù)的使用也不是那么的熟練和完美,對于筆記中的擴(kuò)展事務(wù)控制,傳統(tǒng)的事務(wù)控制,復(fù)制控制等,現(xiàn)在還是停留在認(rèn)知階段。其實(shí),對于事務(wù)和存儲過程,如果寫的足夠完美的話,完全可以將復(fù)雜的業(yè)務(wù)邏輯層給簡化,在D層執(zhí)行對應(yīng)的存儲過程,讓B層簡單實(shí)現(xiàn)D層的接口,這也是其一個(gè)作用吧~~~