DbDataReader с DbTransactions - PullRequest
       7

DbDataReader с DbTransactions

1 голос
/ 14 апреля 2010

Это неправильный путь или недостаток производительности, используя DbDataReader в сочетании с DbTransactions? Пример кода:

public DbDataReader ExecuteReader()
    {
        try
        {
            if (this._baseConnection.State == ConnectionState.Closed)
                this._baseConnection.Open();
            if (this._baseCommand.Transaction != null)
                return this._baseCommand.ExecuteReader();
            return this._baseCommand.ExecuteReader(CommandBehavior.CloseConnection);
        }
        catch (Exception excp)
        {
            if (this._baseCommand.Transaction != null)
                this._baseCommand.Transaction.Rollback();
            this._baseCommand.CommandText = string.Empty;
            this._baseConnection.Close();
            throw new Exception(excp.Message);
        }
    }

Некоторые методы вызывают эту операцию. Иногда открываю транзакцию DbTransaction. Он использует DbConnection и DbCommand.

Реальная проблема заключается в том, что в производственной среде (например, 5000 обращений в день) операции ADO начинают выдавать исключения

У него есть метод, который не открывает транзакцию DbTransaction, но в любом случае выдает исключение.

РЕДАКТИРОВАТЬ: Мы реализовали журнал, чтобы проанализировать операции ADO. Это был подход, чтобы поймать проблемы ADO в производственной среде. Выявлены следующие исключения:

Уже есть открытый DataReader, связанный с этой командой, который должен быть закрыт первым.

Неправильная попытка вызова Read, когда читатель закрыт.

Соединение не было закрыто. Текущее состояние соединения открыто.

Также мы поняли, что класс dbHelper создается следующим образом:

private static readonly dbHelper<T> _instance = new dbHelper<T>();

public static dbHelper<T> GetInstance()
{
    return _instance;
}

И конструкторы DAO устанавливают dbHelper:

this._dataPersist = 
            Registro.Classes.dbHelper<System.Data.SqlClient.SqlClientFactory>.GetInstance();

Мы думаем, что изменение кода доступа к данным, замена универсального dbHelper другим подходом, может решить проблему. Любые предложения будут оценены.

1 Ответ

1 голос
/ 14 апреля 2010

Одна потенциальная проблема заключается в том, что DbTransaction, DbConnection и тому подобное являются абстрактными классами. В какой-то момент вам нужно предоставить реальные конкретные реализации этих типов. Это кажется мне чем-то, что компилятор поймал бы, хотя, но я думал, что это все еще стоит упомянуть.

Скорее всего, вы слишком долго оставляете соединения открытыми. Читая ваше смелое предложение, у меня складывается впечатление, что производственный код изначально не вызывает исключений. Исключения появляются только после того, как вы немного поработали. Это совпадает с кодом, который вы выложили, потому что только в вашем небольшом общем коде я уже вижу два места, где ваш код неправильно очищает свои ресурсы.

Ваша функция execute reader не закроет базовое соединение, если при откате транзакции возникнет исключение. Кроме того, фрагмент, который вы разместили в конце вашего вопроса, может неправильно закрывать читателя. правильный способ распоряжаться вашими ресурсами с помощью блока using, например:

using (var reader = this._dataPersist.ExecuteReader(true))
{
    /* populate the obj here
    * */
}
return obj;

Обратите внимание, что нет необходимости вызывать метод Close () или Dispose (). Блок using позаботится об этом за вас и сделает это , даже если сгенерировано исключение .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...