C#事务处理

 

C#事务处理

 

一:事物的特点(ACID)
1:原子性,要么全部执行,要么全部不执行
2:一致性
3:隔离性
4:持久性

二:操作事务的典型步骤
1:创建一个Connection对象,建立与数据库的连接
    SqlConnection myConnection = new SqlConnection(connectString);
    myConnection.Open();
2:使用Connection.BeginTransaction方法创建一个Transaction对象,启动本地事务。
    SqlTransaction myTrans = myConnection.BeginTransaction();
3:创建一个Command对象
    SqlCommand myCommand = myConnection.CreateCommand();
4:将Transaction对象分配给Command对象的Transaction属性
    myCommand.Transaction = myTrans;
5:执行数据库命令
    cmd.CommandText = "Insert into...."
    cmd.ExecuteNonQuery();
6:根据命令的执行结果调Commit提交事务或Rollback方法取消事务。
    myTrans.Commit();
    myTrans.Rollback();

    if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[InsertOrder]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
    drop procedure [dbo].[InsertOrder]
    --从当前数据库中删除一个或多个存储过程或过程组。
    GO

    SET QUOTED_IDENTIFIER OFF
    --当 SET QUOTED_IDENTIFIER 为 ON 时,标识符可以由双引号分隔,而文字必须由单引号分隔。
    --当 SET QUOTED_IDENTIFIER 为 OFF 时,标识符不可加引号,且必须符合所有 Transact-SQL 标识符规则。
    GO
    SET ANSI_NULLS OFF
    --当设置为 ON 时,所有与空值比较的值都取值为 NULL(未知)。
    --当设置为 OFF 时,如果两个值都为 NULL,则非 Unicode 值与空值比较的值都取值为 TRUE。
    GO
    use northwind
    GO

    --------------------------------------------------
    -- InsertOrder
    --------------------------------------------------
    CREATE PROCEDURE InsertOrder

        @CustomerID     nchar(5),
        @EmployeeID        int,
        @OrderDate         datetime,
        @RequiredDate     datetime,
        @ShippedDate     datetime,
        @ShipAddress     nvarchar(60),
        @Id         int OUTPUT
    AS

        BEGIN TRANSACTION

            -- Insert Values into the Orders table
            INSERT Into Orders(
                CustomerID,
                 EmployeeID,
                OrderDate,
                 RequiredDate,
                 ShippedDate,
                 ShipAddress
                )Values(
                 @CustomerID,
                 @EmployeeID,
                 @OrderDate,
                 @RequiredDate,
                 @ShippedDate,
                 @ShipAddress
                )

            -- Get the new Order Identifier, return as OUTPUT param
            SELECT @Id = @@IDENTITY

        COMMIT TRANSACTION

        RETURN 0
    --------------------------------------------------
    GO
    SET QUOTED_IDENTIFIER OFF
    GO
    SET ANSI_NULLS ON
    GO

三:示例
    public void RunSqlTransaction(string myConnString)
    {
        SqlConnection myConnection = new SqlConnection(myConnString);
        SqlCommand myCommand = myConnection.CreateCommand();
        SqlTransaction myTrans;
        myTrans = myConnection.BeginTransaction();
        myCommand.Connection = myConnection;
        myCommand.Transaction = myTrans;
        try
        {
            myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (100, ´Description´)";
            myCommand.ExecuteNonQuery();
            myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (101, ´Description´)";
            myCommand.ExecuteNonQuery();
            myTrans.Commit();
            Console.WriteLine("Both records are written to database.");
        }
        catch (Exception e)
        {
            try
            {
                myTrans.Rollback();
            }
            catch (SqlException ex)
            {
                if (myTrans.Connection != null)
                {
                    Console.WriteLine("An exception of type " + ex.GetType() +
                        " was encountered while attempting to roll back the transaction.");
                }
            }
            Console.WriteLine("An exception of type " + e.GetType() +
            " was encountered while inserting the data.");
            Console.WriteLine("Neither record was written to database.");
        }
        finally
        {
            myConnection.Close();
        }
    }

 

 

==================================================

一:何时使用事务
    1:在批处理过程中,必须把多个行为作为一个单元插入或删除
    2:只要一个表发生变化,就需要其他表与它同步
    3:同时修改两个或多个数据库中的数据
    4:在分布式事务中,在不同服务器上操作数据库中的数据

二:ACID属性:原子性,一致性,孤立性和持续性
    1:原子性:如果把事务视作单一动作而非各个操作的集合,则它是原子事务。
        只有当所有操作都成功时,事务才成功,并且才会把它提交给数据库。
        如果在事务处理期间有一个操作失败,则认为所有操作都失败,如果操作已经执行,则撤销或回滚。
    2:一致性:事务无论是否成功的完成,都应该让数据库处于一致状态。
        由事务修改的数据必须符合设置在列上的所有约束,以保持数据的完整性。
    3:孤立性:每个事务都有明确定义的界限。
        一个事务不应该影响同时运行的其他事务。
        一个事务完成的数据修改必须独立于其他事务完成的数据修改。
        事务要么看到另一并发事务之前处于原来状态的数据,要么看到第二个事务结束后的数据,但看不到中间状态。
    4:持续性:发生在成功事务内的数据修改将永久保存在系统内,与它们发生的时间无关。
        维护事务日志,如果出现故障,就可以把数据库恢复到其原来的状态。
        完成每个事务时,都在数据库事务日志内对其进行记录。
        如果存在一个主要的系统故障,要求数据库从备份中恢复,将使用这个事务日志插入已经发生的任何成功事务。

三:编写事务的准则
    1:在事务中不需要用户输入
    2:如果可能,不要再浏览数据的时候打开事物
    3:尽量使事物简短
    4:在事物中最小化访问数据

四:在T-SQL中编写事务
    CREATE PROCEDURE sp_Trans_Test
     @newcustid nchar(5), --三个局部变量
     @newcompname nchar(40),
     @oldcustid nchar(5)
    AS
     DECLARE @inserr int
     DECLARE @delerr int
     DECLARE @maxerr int
     SET @maxerr = 0
    BEGIN TRANSACTION
     INSERT into customers(customerid, companyname) VALUES(@newcustid, @newcompname)
     SET @inserr = @@error --保存语句操作的返回结果
     IF(@inserr > @maxerr)
      SET @maxerr = @inserr
     DELETE FROM customers WHERE customerid = @oldcustid
     SET @delerr = @@error --保存语句操作的返回结果
     IF(@delerr > @maxerr)
      SET @maxerr = @delerr
     IF(@maxerr <> 0)
      BEGIN
       ROLLBACK
       PRINT 'Transaction rolled back'
      END
     ELSE
      BEGIN
       COMMIT
       print 'Transaction committed'
      END
     PRINT 'INSERT error number:' + CAST(@inserr AS NVARCHAR(8))
     PRINT 'DELETE error number:' + CAST(@delerr AS NVARCHAR(8))
     return @maxerr;
    1: EXEC sp_Trans_Test 'dd','dd','z'
        (1 行受影响)
        (0 行受影响)
        Transaction committed
        INSERT error number:0
        DELETE error number:0

    2: EXEC sp_Trans_Test 'dd','dd','z'
        The statement has been terminated.
        (0 行受影响)
        Transaction rolled back
        INSERT error number:2627
        DELETE error number:0

五:在ADO.NET中编写事务
    SqlConnection conn = new SqlConnection(@"server=./sqlexpress; integrated security=true; database=northwind");
    String sqlins = @"INSERT into customers(customerid, companyname) VALUES(@newcustid, @newcompname)";
    String sqldel = @"DELETE FROM customers WHERE customerid = @oldcustid";
    SqlTransaction sqltrans = null;
    try
    {
        conn.Open();

        sqltrans = conn.BeginTransaction();

        SqlCommand cmdins = conn.CreateCommand();
        cmdins.CommandText = sqlins;
        cmdins.Transaction = sqltrans;
        cmdins.Parameters.Add("@newcustid", System.Data.SqlDbType.NVarChar, 5);
        cmdins.Parameters.Add("@newcompname", System.Data.SqlDbType.NVarChar, 30);
        cmdins.Parameters["@newcustid"].Value = textBox1.Text;
        cmdins.Parameters["@newcompname"].Value = textBox2.Text;

        SqlCommand cmddel = conn.CreateCommand();
        cmddel.CommandText = sqldel;
        cmddel.Transaction = sqltrans;
        cmddel.Parameters.Add("@oldcustid", System.Data.SqlDbType.NVarChar, 5);
        cmddel.Parameters["@oldcustid"].Value = textBox3.Text;

        cmdins.ExecuteNonQuery();
        cmddel.ExecuteNonQuery();

        sqltrans.Commit();

        MessageBox.Show("transaction committed");
    }
    catch(Exception ex)
    {
        sqltrans.Rollback();
        conn.Close();
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值