交易操作同时与非交易操作混合

时间:2013-01-12 13:20:59

标签: c# .net sql-server-2008 transactions transactionscope

我需要从外部源执行数据导入到我的数据库。因为要下载大量数据,导入执行很长时间,我需要定期更新当前导入状态到数据库(供用户遵循)。

假设我有2个表:Import(导入数据的存储)和Status(导入状态监控表)。

数据导入代码:

public class Importer
{
    public delegate void ImportHandler(string item);
    public event ImportHandler ImportStarted;

    public void OnStart(string item)
    {            
        ImportStarted(item);
    }

    public void Execute(string[] items)
    {
        foreach (var item  in items)
        {
            OnStart(item);                    
            PersistImportedData(Download(item));
        }
    }

    private void PersistImportedData(object data)
    {
        using (var connection = new SqlConnection()){ /*saving imported data*/ }
    }
}

入门代码 - 用于调用导入任务并更新其状态:

public class Starter
{
    public void Process(string[] items)
    {
       var importer = new Importer();
       importer.ImportStarted += UpdateImportState;
       importer.Execute(items);
    }

    private void UpdateImportState(string item)
    {
        using (var connection = new SqlConnection()){ /*status updates*/ }
    }
}

现在一切正常。正在执行导入,并且当导入继续时,用户正在获取状态更新(来自Status表)。

出现问题是因为这种逻辑不安全。我必须确定,导入是原子操作。我不想部分下载和保存数据。我已经使用事务方法作为解决方案(我用importer.Execute包裹了TransactionScope):

importer.ImportStarted += UpdateImportState;
using (var scope = new TransactionScope())
{
    importer.Execute(items);
    scope.Complete();
}

现在我有安全 - 回滚发生,例如在进程中止的情况下。

我现在遇到了不同的问题 - 我要解决的问题。我需要状态更新信息供用户显示,但Status表不受更新影响,而事务尚未完成。即使我尝试使用RequiresNew选项来创建单独的事务(而不是环境1),也没有任何变化。 Execute函数创建自己的数据库连接,UpdateImportState执行相同的操作。连接未共享。我不知道为什么State表不会受到影响,即使TransactionScope仅涵盖与Import表相关的逻辑。

如何保持一致导入并允许定期更新状态?

1 个答案:

答案 0 :(得分:0)

在UpdateImportState中使用TransactionScopeOption.Suppress而不是TransactionScopeOption.RequiresNew