我们建立一个表,两个字段:一个叫 Id(自动编号)、一个叫 Priority(tinyint)。
我们有两条 SQL 语句:一句是插入 Priority 为 1,另一句是插入 Priority 为 256;如果不使用事务,那么第一句会插入成功,第二句由于超出 tinyint 范围,就会失败,最终数据库中会有一条记录。
现在想使用事务,如果第二句插入失败,那么第一句也就回滚。
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["MySqlServer"].ConnectionString))
{
conn.Open();
using (SqlTransaction tran = conn.BeginTransaction())
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.Transaction = tran;
cmd.CommandType = CommandType.Text;
try
{
cmd.CommandText = "insert into TranTable(Priority) values(1)";
cmd.ExecuteNonQuery();
cmd.CommandText = "insert into TranTable(Priority) values(256)";
cmd.ExecuteNonQuery();
tran.Commit();
Response.Write("Ok");
}
catch (SqlException ex)
{
tran.Rollback();
Response.Write("Error:" + ex.Message);
}
}
}
conn.Close();
}
注意:conn.Open() 一定要在 conn.BeginTransaction() 前面,否则出错。
Commit() 用来提交事务,如果产生了异常,就在 catch 块中用 Rollback 回滚事务,这样要么两条记录都插入了,要么一条都没插入。
这种提交、回滚事务都由程序员编程来决定的方式,叫“显式事务(Explicit Transaction)”。
ADO.NET 显式事务占用资源少、速度快,但功能简单,只能管理单一对象和单一持久资源间的事务,比如想在数据库 B 插入失败,则回滚对数据库 A 的操作,就无法用这种 ADO.NET 显式事务来实现。