代码之家  ›  专栏  ›  技术社区  ›  Saif Khan

.NET BackgroundWorker和SQLTransactions

  •  1
  • Saif Khan  · 技术社区  · 15 年前

    在哪里可以找到信息,或者如何在BackgroundWorker线程中处理SQL Server事务?据我所知,错误处理不应在“dowwork”事件中设置,错误是在内部处理并传递给“RunWorkerCompleted”。

    1 回复  |  直到 15 年前
        1
  •  1
  •   Jürgen Steinblock    15 年前

    使用TransactionScope的事务非常简单。

    1. 创建新的TransactionScope(可在using块中预取)

    2. 创建一个新的Sql连接(如果你用另一种方法来连接,它将不起作用)

    3. 运行一些crud操作

    4. ???

    就亚音速而言,这是你必须做的:

    using (var ts = new TransactionScope())
    using (new SubSonic.SharedDbConnectionScope())
    {
    
        DoSomethingWithYourData();
    
        ts.Complete();
    }
    

    背景就是这样:

    如果创建新的TransactionScope,则静态属性Transaction.Current将设置为您的事务。现在,如果您创建了一个新的DbConnection,那么它自己的连接将查看Transaction.Current是否为空并支持TransactionCompleted事件。

    亚音速本身将为您执行的每一条语句创建一个新的连接(没有bug,这是通过设计实现的),但对事务来说并不实用。这就是SharedDbConnectionScope()存在的原因。它的工作原理与TransactionScope类似(如果新的AutomaticConnectionScope检测到当前存在SharedDbConnectionScope(),则将使用它的连接。否则将创建新连接。

    using 语法就是这样:

    var obj = new ObjectThatImplementsIDisposable();
    try
    {
    
    }
    finally
    {
        obj.Dispose();
    }
    

    长话短说:如果您在线程或后台工作程序中运行事务,它不会影响您的事务。但是,您应该记住,如果使用shareddbconnectionscope(),即使来自其他线程的查询也会使用它们,我认为SqlClient库不是线程安全的(但我可能错了,但MySqlClient绝对不是。

    震荡:我会切换到TransactionScope,因为它易于使用、灵活、通用(如果有一天你决定用你的应用程序切换到mysql或oracle,你不必担心)

    阅读问题的第一部分: -我认为让BackGroundWorker的DoWork方法抛出异常是一个糟糕的设计。但您可以使用这种方法:

    private void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        try
        {
             ExecuteATransaction()
        }
        catch (Exception ex)
        {
             RollBackTransaction();
             e.Result = ex;
        }
    }
    
    private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Result && e.Result.GetType() == typeof(Exception))
           throw ((Exception)e.Result);
        else
           Console.WriteLine("Everything went better than expected ;-)");
    }
    
    推荐文章