0

分散トランザクションにエスカレートされない Enterprise Library Data Access Block を使用して、バッチ処理された一連の CRUD 操作を単一のトランザクションで処理するためのベスト プラクティスは何ですか?

完全なソースを編集:

public void BatchInsertEvents(IList<EventItem> events)
{
    _dataAccessBase = new DataAccessBase("[dbo].[EventInsert]");
    int count = 0;

    try
    {
        using (var scope = 
                    new TransactionScope(TransactionScopeOption.RequiresNew))
        {
            foreach (var eventItem in events)
            {
                _dataAccessBase.ClearParameters();

                _dataAccessBase.AddInParameter("@time", 
                                            DbType.String, eventItem.Time);
                ...more params

                _dataAccessBase.ExecuteNonQuery();
                count++;
            }

            scope.Complete();
        }
}

私の DataAccessBase は、データベース オブジェクトの単なるラッパー クラスです。

public class DataAccessBase
{
    private readonly DbCommand _command;
    private readonly Database _database;

    public DataAccessBase(string storedProcName) : this(null, storedProcName)
    {
    }

    public DataAccessBase(string connectionString, string storedProcName)
    {
        _database = string.IsNullOrEmpty(connectionString) ?
                     DatabaseFactory.CreateDatabase() : 
                     DatabaseFactory.CreateDatabase(connectionString);
        _command = _database.GetStoredProcCommand(storedProcName);
    }

    public void AddInParameter<T>(string parameterName, 
                                            DbType parameterType, T value)
    {
        _database.AddInParameter(_command, 
                                parameterName, parameterType, value);
    }


    public void AddOutParameter<T>(string parameterName, 
                                DbType parameterType, int parameterLength)
    {
        _database.AddOutParameter(_command, 
                                parameterName, parameterType, parameterLength);
    }

    public void ClearParameters()
    {
        _command.Parameters.Clear();
    }

    public void ExecuteNonQuery()
    {
        _database.ExecuteNonQuery(_command);
    }
}
4

2 に答える 2

1

起こっていることは、接続プールで EntLib を使用していることだと思います。

その場合、複数の接続にまたがるトランザクションが発生します。これは、分散トランザクションにエスカレートされます。

Entlib が非常に得意とすることの 1 つは、接続を閉じることです。単一の接続を再利用するようにコードを記述する必要があります。

これの一部は、このリンクで説明されています: http://msdn.microsoft.com/en-us/library/cc511672.aspx

それでも問題が解決しない場合は、for each ループ内にコードを投稿してください。

編集

行を移動してみてください:

_dataAccessBase = new DataAccessBase("[dbo].[EventInsert]");

トランザクションスコープ内。

編集2

_dataAccessBase の宣言をトランザクション スコープ内に移動することもできますか

DataAccessBase _dataAccessBase = new DataAccessBase("[dbo].[EventInsert]");

これは、接続がトランザクション スコープ外で使用されないようにするためです。

于 2009-10-11T18:18:12.350 に答える
0

編集: これを投稿した後、私はすでにシラーズ・バイジから与えられたアドバイスをほぼ完全に複製していることに気付きました. 無視してください。

2 回目の試行:

DatabaseFactory.CreateDatabase() のコードを提供してください。偶然そこに追加の TransactionScope がありますか? その場合、同じ TransactionScopeOption.RequiresNew を使用すると、DTC に簡単にエスカレートできます。

于 2009-10-18T04:15:41.063 に答える