一。事物:事務(wù)(Transaction)是并發(fā)控制的單位,是用戶定義的一個(gè)操作序列。這些操作要么都做,要么都不做,是一個(gè)不可分割的工作單位。1.事物是一種機(jī)制,它包含了一組數(shù)據(jù)庫(kù)的操作命令,并且所有的命令作為一個(gè)整體執(zhí)行,在內(nèi)存中執(zhí)行,停在內(nèi)存的臨時(shí)表中,沒(méi) 有去執(zhí)行數(shù)據(jù)庫(kù)的操作。 事物僅對(duì)增、刪、改操作起作用,對(duì)查詢操作沒(méi)有意義。 事物有四個(gè)屬性:原子性(事物是一個(gè)完整的操作) 一致性(事物開(kāi)始和結(jié)束,數(shù)據(jù)要恢復(fù)到開(kāi)始時(shí)的一致?tīng)顟B(tài)) 隔離性(事物的獨(dú)立性,事物之間的操作是相互獨(dú)立的) 持久性(事物完成后對(duì)數(shù)據(jù)庫(kù)的影響是持久的) 2.開(kāi)始事物:begin transaction --指定事物從此開(kāi)始,后面的數(shù)據(jù)庫(kù)操作是一個(gè)整體 提交事物:commit transaction 回滾事物:rollback transaction
通過(guò)事務(wù),SQL Server能將邏輯相關(guān)的一組操作綁定在一起,以便服務(wù)器保持?jǐn)?shù)據(jù)的完整性。
在sql server+ .net 開(kāi)發(fā)環(huán)境下,有兩種方法能夠完成事務(wù)的操作,保持?jǐn)?shù)據(jù)庫(kù)的數(shù)據(jù)完整性;
一個(gè)就是用sql存儲(chǔ)過(guò)程,另一個(gè)就是在ADO.NET中一種簡(jiǎn)單的事務(wù)處理;
現(xiàn)在通過(guò)一個(gè)典型的銀行轉(zhuǎn)賬的例子來(lái)說(shuō)明一下這兩個(gè)例子的用法
我們先來(lái)看看sql存儲(chǔ)過(guò)程是如何來(lái)完成事務(wù)的操作的:
首先創(chuàng)建一個(gè)表:
create database aaaa --創(chuàng)建一個(gè)表,包含用戶的賬號(hào)和錢數(shù)
go
use aaaa
create table bb
(
ID int not null primary key, --賬號(hào)
moneys money --轉(zhuǎn)賬金額
)
insert into bb values ('1','2000') --插入兩條數(shù)據(jù)
insert into bb values ('2','3000')
用這個(gè)表創(chuàng)建一個(gè)存儲(chǔ)過(guò)程:
create procedure mon --創(chuàng)建存儲(chǔ)過(guò)程,定義幾個(gè)變量
@toID int, --接收轉(zhuǎn)賬的賬戶
@fromID int , --轉(zhuǎn)出自己的賬戶
@momeys money --轉(zhuǎn)賬的金額
as
begin tran --開(kāi)始執(zhí)行事務(wù)
update bb set moneys=moneys-@momeys where ID=@fromID -執(zhí)行的第一個(gè)操作,轉(zhuǎn)賬出錢,減去轉(zhuǎn)出的金額
update bb set moneys=moneys+@momeys where ID=@toID --執(zhí)行第二個(gè)操作,接受轉(zhuǎn)賬的金額,增加
if @@error<>0 --判斷如果兩條語(yǔ)句有任何一條出現(xiàn)錯(cuò)誤
begin rollback tran –開(kāi)始執(zhí)行事務(wù)的回滾,恢復(fù)的轉(zhuǎn)賬開(kāi)始之前狀態(tài)
return 0
end
go
else --如何兩條都執(zhí)行成功
begin commit tran 執(zhí)行這個(gè)事務(wù)的操作
return 1
end
go
接下來(lái)看看C#.net 是如何調(diào)用這個(gè)存儲(chǔ)過(guò)程的:
protected void Button1_Click(object sender, EventArgs e)
{
SqlConnection con =new SqlConnection(@"Data Source=.\SQLEXPRESS;database=aaaa;uid=sa;pwd=jcx"); //連接字符串
SqlCommand cmd = new SqlCommand("mon",con); //調(diào)用存儲(chǔ)過(guò)程
cmd.CommandType = CommandType.StoredProcedure;
con.Open();
SqlParameter prar = new SqlParameter();//傳遞參數(shù)
cmd.Parameters.AddWithValue("@fromID", 1);
cmd.Parameters.AddWithValue("@toID", 2);
cmd.Parameters.AddWithValue("@momeys",Convert.ToInt32( TextBox1.Text) );
cmd.Parameters.Add("@return", "").Direction = ParameterDirection.ReturnValue;//獲取存儲(chǔ)過(guò)程的返回值
cmd.ExecuteNonQuery();
string value = cmd.Parameters["@return"].Value.ToString();//把返回值賦值給value
if (value == "1")
{
Label1.Text = "添加成功";
}
else
{
Label1.Text = "添加失敗";
}
}
這個(gè)也就是在存儲(chǔ)過(guò)程里添加事務(wù),再來(lái)看看不在數(shù)據(jù)庫(kù)寫sql存儲(chǔ)過(guò)程,ADO.NET是如何處理事務(wù)的:
protected void Button2_Click(object sender, EventArgs e)
{
SqlConnection con = new SqlConnection(@"Data Source=.\SQLEXPRESS;database=aaaa;uid=sa;pwd=jcx");
con.Open();
SqlTransaction tran = con.BeginTransaction();//先實(shí)例SqlTransaction類,使用這個(gè)事務(wù)使用的是con這個(gè)連接,使用BeginTransaction這個(gè)方法來(lái)開(kāi)始執(zhí)行這個(gè)事務(wù)
SqlCommand cmd = new SqlCommand();
cmd.Connection = con;
cmd.Transaction = tran;
try
{
//在try{}塊里執(zhí)行sqlcommand命令,
cmd.CommandText = "update bb set moneys=moneys-'" + Convert.ToInt32(TextBox1.Text) + "' where ID='1'";
cmd.ExecuteNonQuery();
cmd.CommandText = "update bb set moneys=moneys+' aa ' where ID='2'";
cmd.ExecuteNonQuery();
tran.Commit();//如果兩個(gè)sql命令都執(zhí)行成功,則執(zhí)行commit這個(gè)方法,執(zhí)行這些操作
Label1.Text = "添加成功";
}
catch
{
Label1.Text = "添加失敗";
tran.Rollback();//如何執(zhí)行不成功,發(fā)生異常,則執(zhí)行rollback方法,回滾到事務(wù)操作開(kāi)始之前;
}
}
這就是兩個(gè)事務(wù)不同用法的簡(jiǎn)單例子,ADO.NET事務(wù)處理的方法看起來(lái)比較簡(jiǎn)單,但是他要使用同一個(gè)連接來(lái)執(zhí)行這些操作,要是同時(shí)使用幾個(gè)數(shù)據(jù)庫(kù)來(lái)用一個(gè)事務(wù)執(zhí)行,這樣就比較繁瑣,但是要是用sql存儲(chǔ)過(guò)程,這樣就相對(duì)比較簡(jiǎn)單,總之是兩種方法各有各的優(yōu)點(diǎn)。
聯(lián)系客服