日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

关于使用Transaction对于非数据库事务的操作

發布時間:2023/12/10 数据库 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于使用Transaction对于非数据库事务的操作 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在操作數據庫的過程中,為了數據的一致性,我們可以使用Transaction,要么成功的時候全部提交,要么有任何一個操作失敗立即全部回滾。不僅僅是在數據庫方面,有時候操作其他的內容,比如說對于系統文件的操作,也需要把一些操作組合看做是一個事務。

?

現在我們看這樣一個例子。現在我們需要在計算機的硬盤上創建3個目錄A,B,C,要求要么3個全部創建成功,要么一個也不要創建。我們可以把這個看成是一個事務。如果我們自己寫代碼來操作,可以這樣寫。

?

[csharp]?view plaincopy
  • bool?createA?=?false;??
  • bool?createB?=?false;??
  • bool?createC?=?false;??
  • ??
  • try??
  • {??
  • ????//這里的操作是創建3個目錄??
  • ????Directory.CreateDirectory("\\A");??
  • ????createA?=?true;??
  • ????Directory.CreateDirectory("\\B");??
  • ????createB?=?true;??
  • ????Directory.CreateDirectory("\\C");??
  • ????createC?=?true;??
  • }??
  • catch?(System.Exception?ex)??
  • {??
  • ????//這里在捕捉到異常時,根據運行的結果進行回滾??
  • ????if?(createB)??
  • ????{??
  • ????????Directory.Delete("\\B");??
  • ????????Directory.Delete("\\A");??
  • ????}??
  • ????if?(!createB?&&?createA)??
  • ????{??
  • ????????Directory.Delete("\\A");??
  • ????}??
  • }??


  • ?

    但是這里我們是把這3個操作當成一個整體來回滾,及時是簡單的創建刪除文件夾,我們可以看到catch中的回滾邏輯已經很復雜了。可以想象,如果A,B,C這3步不僅僅是創建目錄,還有一些其他的操作,那么回滾的邏輯就非常復雜,此時,我們可以考慮把這一個分成幾個小事務,分開回滾。代碼可以這樣寫,這里我們使用了Framework提供的Transactin以及TransactioScope類。

    ?

    [csharp]?view plaincopy
  • class?Program??
  • ????{??
  • ????????static?void?Main(string[]?args)??
  • ????????{??
  • ????????????//這里就不需要了try?catch,因為scope就已經完成了這個功能,??
  • ????????????//即當有異常發生向外拋的時候,會嘗試跳出這個using代碼塊,??
  • ????????????//CLR會在向代碼塊外邊跑異常之前,分別取調用每個transaction的??
  • ????????????//roolback方法,只要rollback中你定義的邏輯沒有問題,那么所有??
  • ????????????//的已發生的操作就會安全的回滾。??
  • ????????????using?(var?scope?=?new?TransactionScope())??
  • ????????????{??
  • ????????????????var?A?=?new?OperationA();??
  • ????????????????Transaction.Current.EnlistVolatile(A,?EnlistmentOptions.None);??
  • ????????????????A.DoWork();??
  • ??
  • ????????????????OperationB?B?=?new?OperationB();??
  • ????????????????Transaction.Current.EnlistVolatile(B,?EnlistmentOptions.None);??
  • ????????????????B.DoWork();??
  • ????????????????scope.Complete();??
  • ????????????}??
  • ????????}??
  • ??
  • ??
  • ????}??
  • }??
  • ??
  • class?OperationA?:?IEnlistmentNotification??
  • {??
  • ????private?bool?_isCommitSucceed?=?false;??
  • ??
  • ????public?void?Commit(Enlistment?enlistment)??
  • ????{??
  • ????????enlistment.Done();??
  • ????}??
  • ??
  • ????public?void?DoWork()//這是自定義的方法,不是繼承IEnlistmentNotification??
  • ????{??
  • ????????Directory.CreateDirectory("\\A");??
  • ????????//這里還有一些其他的關于A的復雜操作??
  • ????????_isCommitSucceed?=?true;??
  • ????}??
  • ??
  • ????public?void?InDoubt(Enlistment?enlistment)??
  • ????{??
  • ????????enlistment.Done();??
  • ????}??
  • ????public?void?Prepare(PreparingEnlistment?preparingEnlistment)??
  • ????{??
  • ????????preparingEnlistment.Prepared();??
  • ????}??
  • ????public?void?Rollback(Enlistment?enlistment)??
  • ????{??
  • ????????//這里回滾A的一些操作,當然這里的操作邏輯需要你自己來寫。??
  • ????????//比如說查看是否創建成功,或者有一些其他的信號標記,通過這些??
  • ????????//標記你來決定是刪除目錄還是其他的什么回滾操作。??
  • ????????if?(_isCommitSucceed)??
  • ????????????Directory.Delete("\\A");??
  • ????????enlistment.Done();??
  • ????}??
  • }??
  • ??
  • class?OperationB?:?IEnlistmentNotification??
  • {??
  • ????private?bool?_isCommitSucceed?=?false;??
  • ??
  • ????public?void?Commit(Enlistment?enlistment)??
  • ????{??
  • ????????enlistment.Done();??
  • ????}??
  • ??
  • ????public?void?DoWork()??
  • ????{??
  • ????????//這里是關于B的一些復雜操作??
  • ????????throw?new?Exception("test");??
  • ????????//這里依然有一些操作代碼,但是我們模擬的是B操作途中拋出異常,所以這里的代碼不會執行??
  • ????}??
  • ??
  • ????public?void?InDoubt(Enlistment?enlistment)??
  • ????{??
  • ????????enlistment.Done();??
  • ????}??
  • ????public?void?Prepare(PreparingEnlistment?preparingEnlistment)??
  • ????{??
  • ????????preparingEnlistment.Prepared();??
  • ????}??
  • ????public?void?Rollback(Enlistment?enlistment)??
  • ????{??
  • ????????if?(_isCommitSucceed)??
  • ????????{??
  • ????????????//這里回滾B的一些已經存在的操作。??
  • ????????}??
  • ????????enlistment.Done();??
  • ????}??

  • 這里的機制是這樣的,可能是scope.Complete()方法中有某種特別的操作,去告訴CLR這次所有的操作都順利完成了,在跳出這個scope的時候就不用調用那些transaction的rollback方法了。如果沒有執行到scope.Complete()方法,那么就會在跳出這個scope代碼塊的時候調用rollback方法。一般造成這個的原因是在某個transaction的邏輯操作中出現異常,造成從此次直接拋出異常跳出這個代碼塊,沒有機會執行下邊的代碼。可以看出這里的重點也是寫rollback的邏輯,但是相對于原來的catch中的邏輯,這里分開為多個小的邏輯,相對來說容易了很多。

    這只是個人寫的一種使用回滾的邏輯。在使用IEnlistmentNotification的時候,也有人把業務邏輯寫入到Commit中。如果想真正理解transaction回滾的機制,建議深入理解一下TransactionScope與Transactiond的實現機制。

    轉載于:https://www.cnblogs.com/sky6699/p/4535760.html

    總結

    以上是生活随笔為你收集整理的关于使用Transaction对于非数据库事务的操作的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。