0

外部ソースからデータベースへのデータ インポートを実行する必要があります。ダウンロードするデータが多いため、インポートは長時間実行され、現在のインポート状態に関する定期的な更新をデータベースに保持する必要があります (ユーザーがフォローできるようにするため)。

Import(インポートされたデータのストレージ) とStatus(状態監視テーブルのインポート) の2 つのテーブルがあるとします。

データ インポートのコード:

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別のトランザクション (アンビエント トランザクションではない) を作成するオプションを使用しようとしても、何も変わりません。このExecute関数は、データベースへの独自の接続を作成UpdateImportStateし、同じことを行います。接続は共有されません。テーブルに接続されたロジックのみをカバーしているのにState、なぜテーブルが影響を受けないのかわかりません。TransactionScopeImport

一貫したインポートを維持し、定期的なステータス更新を許可する方法は?

4

1 に答える 1

0

TransactionScopeOption.RequiresNew の代わりに、UpdateImportState で TransactionScopeOption.Suppress を使用します。

于 2013-01-12T14:01:11.263 に答える