Передовая практика управления транзакциями блоков доступа к библиотеке данных - PullRequest
0 голосов
/ 08 октября 2009

Какова лучшая практика обработки пакетной серии операций 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();
        }
}

My DataAccessBase - это просто класс-оболочка для объекта Database

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);
    }
}

Ответы [ 2 ]

1 голос
/ 11 октября 2009

Я предполагаю, что происходит то, что вы используете EntLib с пулами соединений.

Что происходит тогда, когда вы получаете транзакцию, которая распространяется более чем на одно соединение. Затем он преобразуется в распределенную транзакцию.

Одна вещь, в которой Энтлиб очень хорош, это закрытие соединений. Вы должны написать свой код таким образом, чтобы он повторно использовал одно соединение.

Часть этого объяснена в этой ссылке: http://msdn.microsoft.com/en-us/library/cc511672.aspx

Если у вас все еще есть проблемы, опубликуйте свой код в каждом цикле.

EDIT

Попробуйте переместить строку:

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

внутри области транзакции.

РЕДАКТИРОВАТЬ 2

Можете ли вы переместить объявление _dataAccessBase в область транзакции

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

Это просто для того, чтобы убедиться, что соединение не используется за пределами области транзакции.

0 голосов
/ 18 октября 2009

Редактировать: После публикации я понял, что почти полностью продублировал совет, который уже дал Шираз Бхайджи. Пожалуйста, игнорируйте.

Вторая попытка:

Пожалуйста, предоставьте код для DatabaseFactory.CreateDatabase (). У вас есть дополнительный TransactionScope случайно? Если это так, и вы используете тот же TransactionScopeOption.RequiresNew, вы можете легко перейти к DTC.

...