.NET事务范围选项

8

我是一个C#的新手。所以我想知道有没有人可以帮我弄清楚C#如何使用transactionscope?因为我对它的定义有点困惑。不过,让我稍微解释一下我的问题,这样你就会知道我试图实现什么。

我声明了三个表适配器,分别用于三个不同的数据集,如下所示:

logTableAdapter logAdap = new logTableAdapter();
measTableAdapter measAdap = new measTableAdapter();
valueTableAdapter valueAdap = new valueTableAdapter();

导入数据的过程如下:
  1. 首先通过logAdap.insert()方法插入日志条目。
  2. 循环遍历Excel文件以获取测量值,并通过measAdap.insert()方法开始插入。
  3. 对于每个测量值,我都会通过valueAdap.insert()方法插入值。
所以我的问题是 - 由于测量值和值之间存在嵌套关系。我该如何创建一个嵌套的TransactionScope,当任何错误发生时(测量值插入/值插入),我只想回滚我所做的一切。也就是说,我只想回到插入日志条目之前的状态。

顺便说一句,“C#.NET”这个东西并不存在。它只是“C#”。 - John Saunders
3个回答

3
引用这篇文章的恰当名称:The definitive TableAdapters + Transactions blog post
如果您在一个TransactionScope中处理复数操作,即“GetData”和“Update”都在单个TransactionScope内,或者在TransactionScope内有两个Update操作,则会有效地打开两个SqlConnection到单个数据库,从而不必要地将事务从本地事务管理器提升到分布式事务协调程序。作为最佳实践,始终仅在TransactionScope内包装单个操作。如果您选择在单个TransactionScope内包装多个操作,则必须通过扩展部分类定义自己管理连接生命周期。换句话说,以下代码将导致事务升级 -
using (TransactionScope tsc = new TransactionScope())
{
    tableAdap.GetData() ;
    //Do your transactional work.
    tableAdap.Update() ;
    tsc.Complete() ;
}

但是以下代码完全没有问题 -
using (TransactionScope tsc = new TransactionScope())
{

    tableAdap.OpenConnection() ;
    tableAdap.GetData() ;

    //Do your transactional work.
    tableAdap.Update() ;
    tableAdap.CloseConnection() ;
    tsc.Complete() ;
} 

所以你只需要一个TransactionScope,但有一些注意事项。这是要点,但我鼓励你阅读博客文章。 TableAdapters不是高完整性事务系统最合适的数据访问方法。如果你需要更可靠性,你应该将操作编写为存储过程,并从你的C#代码中执行它。

0

我认为您要找的是如何使用TransactonScope,因此我将修改您在评论中提供的示例。下面是您的代码:

using( TransactionScope ts = new TransactionScope() ) { 
    try 
    { 
        logAdap.InsertLog(.....);

        foreach (.....)
        {
            measAdap.InsertMeas(.....); 
            foreach (.....)
            {
                valAdap.InsertVal(.....);
            }
        }

        // Complete the transaction
        ts.Complete();
    }
    catch (Exception ex) 
    { 
        // Your error handling here.
        // No need to rollback each table adapter. That along with all the 
        // transaction is done for you when exiting the using block without 
        // calling Complete() on the TransactionScope.
    }}

这种使用范围的方式被称为隐式事务,您可以在此MSDN文章中获得很好的概述:使用Transaction Scope实现隐式事务

话虽如此,正如fencliff所提到的,您可能不想为您的情况打开多个连接,从而节省宝贵的数据库资源。


0

你不需要超过一个TransactionScope,我想你可以在同一个事务范围内完成所有操作。


所以你认为伪代码应该是这样的:code using(TransactionScope ts = new TransactionScope()) { try { foreach (.....) { measAdap.InsertMeas(.....); foreach (.....) { valAdap.InsertVal(.....); } }measAdap.Commit() ; valAdap.Commit(); } catch (Exception ex) { measAdap.Rollback(); valAdap.Rollback(); } } code - Mystic
@Mystic 如果按照这种逻辑,事务将被升级为使用分布式事务协调器。这个SO答案告诉你为什么你可能不想要那个:http://bit.ly/gGampm - 请查看我的答案以获取解决方法。 - jevakallio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接