本文將涉及到在
.net
框架下使用
c#語言操縱資料庫事務的各個方面。
體驗sql語言的事務機制
作為大型的企業級資料庫,
sql server2000
對事務提供了很好的支援。我們可以使用
sql語句來定義、提交以及回滾乙個事務。
如下所示的
sql**定義了乙個事務,並且命名為
"mytransaction"
(限於篇幅,本文並不討論如何編寫
sql
declare @tranname varchar(20)
select @tranname = 'mytransaction'
begin transaction @trannamegouse pubs
goupdate roysched
set royalty = royalty * 1.10
where title_id like 'pc%'
gocommit transaction mytransactiongo
這裡用到了
sql server2000
自帶的示例資料庫
pubs
,提交事務後,將為所有暢銷計算機書籍支付的版稅增加
10%。
開啟
sql server2000
的查詢分析器,選擇
pubs
資料庫,然後執行這段程式,結果顯而易見。
可是如何在
c#程式中執行呢?我們記得在普通的
sql查詢中,一般需要把查詢語句賦值給
salcommand.commandtext
屬性,這裡也就像普通的
sql查詢語句一樣,將這些語句賦給
sqlcommand.commandtext
屬性即可。要注意的一點是,其中的
"go"
語句標誌著
sql批處理的結束,編寫
sql指令碼是需要的,但是在這裡是不必要的。我們可以編寫如下的程式來驗證這個想法:
//transql.csusing system;
using system.data;
using system.data.sqlclient;
namespace aspcn
catch(exception err)
finally
}file://
獲取資料連線
private sqlconnection getconn()
}public class test}}
注意到其中的
sqlcommand
物件mycomm
,它的commandtext
屬性僅僅是前面
sql**字串連線起來即可,當然,其中的
"go"
語句已經全部去掉了。這個語句就像普通的查詢一樣,程式將
sql文字事實上提交給
dbms
去處理了,然後接收返回的結果(如果有結果返回的話)。
很自然,我們最後看到了輸出
"事務處理已經成功完成
",再用企業管理器檢視
pubs
資料庫的
roysched
表,所有
title_id
欄位以"pc"
開頭的書籍的
royalty
欄位的值都增加了
0.1倍。
這裡,我們並沒有使用
ado.net
的事務處理機制,而是簡單地將執行事務的
sql語句當作普通的查詢來執行,因此,事實上該事務完全沒有用到
.net
的相關特性。
了解.net
中的事務機制
如你所知,在
.net
框架中主要有兩個命名空間
(namespace)
用於應用程式同資料庫系統的互動:
system.data.sqlclient
和system.data.oledb
。前者專門用於連線
microsoft
公司自己的
sql server
資料庫,而後者可以適應多種不同的資料庫。這兩個命名空間中都包含有專門用於管理資料庫事務的類,分別是
system.data.sqlclient.sqltranscation
類和system.data.oledb.oledbtranscation
類。
就像它們的名字一樣,這兩個類大部分功能是一樣的,二者之間的主要差別在於它們的連線機制,前者提供一組直接呼叫
sql server
的物件,而後者使用本機
ole db
啟用資料訪問。
事實上,
ado.net
事務完全在資料庫的內部處理,且不受
microsoft
分布式事務處理協調器
(dtc)
或任何其他事務性機制的支援。本文將主要介紹
system.data.sqlclient.sqltranscation
類,下面的段落中,除了特別註明,都將使用
system.data.sqlclient.sqltranscation
類。
事務的開啟和提交
現在我們對事務的概念和原理都了然於心了,並且作為已經有一些基礎的
c#開發者,我們已經熟知編寫資料庫互動程式的一些要點,即使用
sqlconnection
類的物件的
open()
方法建立與資料庫伺服器的連線,然後將該連線賦給
sqlcommand
物件的connection
屬性,將欲執行的
sql語句賦給它的
commandtext
屬性,於是就可以通過
sqlcommand
物件進行資料庫操作了。對於我們將要編寫的事務處理程式,當然還需要定義乙個
sqltransaction
型別的物件。並且看到
sqlcommand
物件的transcation
屬性,我們很容易想到新建的
sqltransaction
物件應該與它關聯起來。
基於以上認識,下面我們就開始動手寫我們的第乙個事務處理程式。我們可以很熟練地寫出下面這一段程式:
//dotran.csusing system;
using system.data;
using system.data.sqlclient;
namespace aspcn
catch(exception err)
finally
}file://
獲取資料連線
private sqlconnection getconn()
}public class test}}
顯然,這個程式非常簡單,我們非常自信地編譯它,但是,出乎意料的結果使我們的成就感頓時煙消雲散:
error cs1501:
過載"sqltransaction"
方法未獲取
"0"引數
是什麼原因呢?注意到我們初始化的**:
sqltransaction mytran=new sqltransaction();
顯然,問題出在這裡,事實上,
sqltransaction
類並沒有公共的建構函式,我們不能這樣新建乙個
sqltrancaction
型別的變數。在事務處理之前確實需要有乙個
sqltransaction
型別的變數,將該變數關聯到
sqlcommand
類的transcation
屬性也是必要的,但是初始化方法卻比較特別一點。在初始化
sqltransaction
類時,你需要使用
sqlconnection
類的begintranscation()
方法:
sqltransaction mytran; mytran=myconn.begintransaction();
該方法返回乙個
sqltransaction
型別的變數。在呼叫
begintransaction()
方法以後,所有基於該資料連線物件的
sql語句執行動作都將被認為是事務
mytran
的一部分。同時,你也可以在該方法的引數中指定事務隔離級別和事務名稱,如:
sqltransaction mytran;
mytran=myconn.begintransaction(isolationlevel.readcommitted,"sampletransaction");
關於隔離級別的概念我們將在隨後的內容中**,在這裡我們只需牢記乙個事務是如何被啟動,並且關聯到特定的資料鏈結的。
先不要急著去搞懂我們的事務都幹了些什麼,看到這一行:
mytran.commit();
是的,這就是事務的提交方式。該語句執行後,事務的所有資料庫操作將生效,並且為資料庫事務的永續性機制所保持
--即使系統在這以後發生致命錯誤,該事務對資料庫的影響也不會消失。
對上面的程式做了修改之後我們可以得到如下**(為了節約篇幅,重複之處已省略,請參照前文):
//dotran.cs……
}file://
執行事務處理
public void dotran()
catch(exception err)
finally}……
到此為止,我們僅僅掌握了如何開始和提交事務。下一步我們必須考慮的是在事務中可以幹什麼和不可以幹什麼。
C 資料庫事務原理及實踐
什麼是資料庫事務 資料庫事務是指作為單個邏輯工作單元執行的一系列操作。設想網上購物的一次交易,其付款過程至少包括以下幾步資料庫操作 更新客戶所購商品的庫存資訊 儲存客戶付款資訊 可能包括與銀行系統的互動 生成訂單並且儲存到資料庫中 更新使用者相關資訊,例如購物數量等等 正常的情況下,這些操作將順利進...
C 資料庫事務原理
隔離級別的概念 企業級的資料庫每一秒鐘都可能應付成千上萬的併發訪問,因而帶來了併發控制的問題。由資料庫理論可知,由於併發訪問,在不可預料的時刻可能引發如下幾個可以預料的問題 髒讀 包含未提交資料的讀取。例如,事務1 更改了某行。事務2 在事務1 提交更改之前讀取已更改的行。如果事務1 回滾更改,則事...
資料庫事務及實現
一 事務 事務指的是滿足acid特性的一組操作,可以通過 commit提交乙個事務,也可以使用 rollback 進行回滾。mysql 預設採用自動提交模式。也就是說,如果不顯式使用start transaction語句來開始乙個事務,那麼每個查詢都會被當做乙個事務自動提交。acid 1.原子性 a...