11事务
1事务范围-TransactionScope
1.1 交易管理员会决定要参与哪个事务。
1.2 调用Complete 方法,提交事务。
1.3 如果有异常在事务范围内发生,则会复原范围所参与的事务。
2 添加dll
System.Transactions.dll
3 代碼
/// <summary>
/// 測試事務範圍
/// </summary>
private void btnTrans_Click(object sender, EventArgs e)
{
// 1 刪除所有
// 2 添加一條新的記錄
// 3 修改一條記錄
// 4 添加一條已經存在記錄(違反PK)
using (System.Transactions.TransactionScope tx = new System.Transactions.TransactionScope())
{
try
{
// 刪除所有
try
{
Customer cust = db.Customers.Single<Customer>(n => n.CustomerID == "JIM");
if (cust != null)
{
db.Customers.DeleteOnSubmit(cust);
db.SubmitChanges();
}
}
catch (Exception ex)
{
// 經實踐,要拋出異常,不可忽略
// 一定要throw
throw ex;
//MessageBox.Show(ex.Message);
}
try
{
// 添加一條記錄-預期成功
object[] para = { "JIM", "TOM", "TOM", "other", "other2" };
int ret = db.ExecuteCommand(" INSERT INTO Customers(CustomerID, CompanyName, ContactName) VALUES({0},{1},{2}) ", para);
// 修改一條記錄-預期成功
object[] paraUpdate = { "TOMx", "TOMx", "JIM" };
db.ExecuteCommand(" UPDATE Customers SET CompanyName={0}, ContactName={1} WHERE CustomerID={2} ", paraUpdate);
// 添加一條記錄-預期失敗,違反主鍵約束
db.ExecuteCommand(" INSERT INTO Customers(CustomerID, CompanyName, ContactName) VALUES({0},{1},{2}) ", para);
}
catch (Exception ex)
{
// 經實踐,要拋出異常,不可忽略
// 一定要throw
throw ex;
//MessageBox.Show(ex.Message);
}
tx.Complete();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
} // end private void btnTrans_Click(object sender, EventArgs e)
注意:事务范围从{开始,到}结束。
(2)事务范围内,代码有异常一定得抛出。因为TransactionScope根据异常判断是否有错。
(3)必须调用Complete()方法。因为需要提交到数据库,并且保存到数据库。
4 学习资源
4.1MSDN TransactionScope 例子
// This function takes arguments for 2 connection strings and commands to create a transaction
// involving two SQL Servers. It returns a value > 0 if the transaction is committed, 0 if the
// transaction is rolled back. To test this code, you can connect to two different databases
// on the same server by altering the connection string, or to another 3rd party RDBMS by
// altering the code in the connection2 code block.
static public int CreateTransactionScope(
string connectString1, string connectString2,
string commandText1, string commandText2)
{
// Initialize the return value to zero and create a StringWriter to display results.
int returnValue = 0;
System.IO.StringWriter writer = new System.IO.StringWriter();
// Create the TransactionScope to execute the commands, guaranteeing
// that both commands can commit or roll back as a single unit of work.
using (TransactionScope scope = new TransactionScope())
{
using (SqlConnection connection1 = new SqlConnection(connectString1))
{
try
{
// Opening the connection automatically enlists it in the
// TransactionScope as a lightweight transaction.
connection1.Open();
// Create the SqlCommand object and execute the first command.
SqlCommand command1 = new SqlCommand(commandText1, connection1);
returnValue = command1.ExecuteNonQuery();
writer.WriteLine("Rows to be affected by command1: {0}", returnValue);
// If you get here, this means that command1 succeeded. By nesting
// the using block for connection2 inside that of connection1, you
// conserve server and network resources as connection2 is opened
// only when there is a chance that the transaction can commit.
using (SqlConnection connection2 = new SqlConnection(connectString2))
try
{
// The transaction is escalated to a full distributed
// transaction when connection2 is opened.
connection2.Open();
// Execute the second command in the second database.
returnValue = 0;
SqlCommand command2 = new SqlCommand(commandText2, connection2);
returnValue = command2.ExecuteNonQuery();
writer.WriteLine("Rows to be affected by command2: {0}", returnValue);
}
catch (Exception ex)
{
// Display information that command2 failed.
writer.WriteLine("returnValue for command2: {0}", returnValue);
writer.WriteLine("Exception Message2: {0}", ex.Message);
}
}
catch (Exception ex)
{
// Display information that command1 failed.
writer.WriteLine("returnValue for command1: {0}", returnValue);
writer.WriteLine("Exception Message1: {0}", ex.Message);
}
}
// The Complete method commits the transaction. If an exception has been thrown,
// Complete is not called and the transaction is rolled back.
scope.Complete();
}
// The returnValue is greater than 0 if the transaction committed.
if (returnValue > 0)
{
writer.WriteLine("Transaction was committed.");
}
else
{
// You could write additional business logic here, for example, you can notify the caller
// by throwing a TransactionAbortedException, or logging the failure.
writer.WriteLine("Transaction rolled back.");
}
// Display messages.
Console.WriteLine(writer.ToString());
return returnValue;
}
人的一生应该这样度过:当他回首往事的时候,不会因为虚度年华而悔恨,也不会因为碌碌无为而羞愧。
浙公网安备 33010602011771号