65.9K
CodeProject 正在变化。 阅读更多。
Home

更轻松地处理数据库事务 - 扩展 Using 语句以执行自动数据库事务

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.47/5 (20投票s)

2004年10月25日

2分钟阅读

viewsIcon

122506

downloadIcon

978

任何进行数据库更新的用户都会使用事务。在 ADO.NET 中,事务使用事务对象和 try..catch 来完成,但是有一种更简单的方法,甚至可以说是一种更 C# 的方式来处理数据库事务。

概述

任何进行数据库更新的用户都会使用事务。在 ADO.NET 中,事务使用事务对象和 try..catch 来完成,但是有一种更简单的方法,甚至可以说是一种更 C# 的方式来处理数据库事务。

Visual Basic .NET 用户

因为此技术依赖于 C# 特有的 using 语句,所以此技术不能应用于 Visual Basic .NET。 然而,有传言说 Visual Studio .NET 2005 将为 Visual Basic 包含类似的语句。

正常的事务处理方式

这是一个正常的数据库事务处理的示例。 这是 MSDN 上的示例的简化版本。

using (OleDbTransaction xTx = _DB.BeginTransaction()) {
    try {
        OleDbCommand xCmd = _DB.CreateCommand();
        xCmd.Transaction = xTx;
        xCmd.CommandText = "Insert into Person (Name, Telephone)" + 
                           " values ('Normal One', '(412) 555-1212')";
        xCmd.ExecuteNonQuery();
        if (chckThrow.Checked) {
            throw new Exception("Test Exception");
        }
        xCmd.CommandText = "Insert into Person (Name, Telephone)" + 
                           " values ('Normal Two', '(423) 555-1212')";
        xCmd.ExecuteNonQuery();
        xTx.Commit();
    }
    catch (Exception xException) {
        xTx.Rollback();
        throw xException;
    }
}

简单的事务处理方式

使用我的方法,代码执行相同的操作,但变得更短、更简洁,甚至更像 C#。

using (Transaction xTx = new Transaction(_DB)) {
    OleDbCommand xCmd = _DB.CreateCommand();
    ((IDbCommand)xCmd).Transaction = xTx.DBTransaction;
    xCmd.CommandText = "Insert into Person (Name, Telephone)" + 
                       " values ('Object One', '(412) 555-1212')";
    xCmd.ExecuteNonQuery();
    if (chckThrow.Checked) {
        throw new Exception("Test Exception");
    }
    xCmd.CommandText = "Insert into Person (Name, Telephone)" + 
                       " values ('Object Two', '(423) 555-1212')";    
    xCmd.ExecuteNonQuery();
    xTx.Commit();
}

演示项目

演示项目演示了这一点,并允许模拟异常。 为了简单起见,演示项目使用包含的 Access 数据库文件。 但是,包含的类适用于任何 ADO.NET 数据源。

工作原理

C# 中的 using 语句导致在退出块时调用 dispose。 通过实现 Dispose,并检查事务是否已提交,事务类可以确定是否调用回滚。 无需重新抛出可能正在进行的任何异常,因为 C# 会自动继续异常路径,作为处理 using 块的一部分。

事务类源代码

public class Transaction : IDisposable {

    private IDbConnection _DB;
    private IDbTransaction _DBTransaction;

    public IDbTransaction DBTransaction {
      get { return _DBTransaction; }
    }

    public Transaction(IDbConnection aDB) : this(aDB, true) {
    }

    public Transaction(IDbConnection aDB, bool aHandle) {
      if (aHandle) {
        _DB = aDB;
        _DBTransaction = _DB.BeginTransaction();
      }
    }

    public void Commit() {
      if (_DB != null) {
        _DBTransaction.Commit();
        _DBTransaction.Dispose();
        _DB = null;
      }
    }

    public void Dispose() {
      if (_DB != null) {
        _DBTransaction.Rollback();
        _DBTransaction.Dispose();
        _DB = null;
      }
    }
}

结论

此类纯粹为您的代码添加语法糖,并使执行事务变得更容易。 功能相同。 但是,当处理事务并且必须每次手动创建此结构时,较短的版本更容易键入,并且在再次处理代码时也更容易阅读。

© . All rights reserved.