Как сказать, имеет ли SqlConnection приложенный SqlDataReader?

Это походит на проблему со зрением. Вы могли бы хотеть изучить Адаптивное Повышение, а также алгоритм Извлечения Строки Записей. Понятия в этих двух должны помочь с приближением к этой проблеме. Граничное обнаружение является еще более простым местом, чтобы запуститься, если Вы плохо знакомы с алгоритмами визуализации, поскольку оно объясняет основы.

До параметров для классификации:

  • Цветовая палитра & Местоположение (Вычисление градиента, гистограмма цветов)
  • Содержавшие Формы (Ada. Повышение/Обучение для обнаружения форм)
12
задан Earlz 16 July 2010 в 18:29
поделиться

9 ответов

как SqlConnection узнает, что к нему подключен

Насколько я могу судить, SQLConnection знает, что к нему присоединен читатель, потому что он поддерживает внутреннюю ссылку на него.

Разумное использование Reflector показывает, что объект SQLConnection имеет приватное поле типа DBConnectionInternal, которое заполнено одной из нескольких конкретных реализаций этого абстрактного класса. Когда вы пытаетесь добавить второго живого читателя к соединению, метод 'ValidateConnectionForExecute' вызывается на внутреннем соединении, и это приводит к исследованию внутренней 'ReferenceCollection'. Если при этом обнаруживается существующий живой читатель, возникает исключение.

Полагаю, при желании все это можно вычислить самостоятельно во время выполнения с помощью рефлексии.

13
ответ дан 2 December 2019 в 04:25
поделиться

Чтобы убедиться, что вы закрыли свои носители данных (и соединения с базой данных), всегда открывайте их в блоке using, например:

using (SqlDataReader rdr = MySqlCommandObject.ExecuteReader())
{
    while (rdr.Read())
    {
        //...
    }
} // The SqlDataReader is guaranteed to be closed here, even if an exception was thrown.
13
ответ дан 2 December 2019 в 04:25
поделиться

Чтобы избежать этого, оберните свой DataReader в блок using, это гарантирует, что он будет располагать соединение следующим образом:

using (IDataReader reader = command.ExecuteReader())
{
      //do stuff
}

В IDataReader есть свойство IsClosed, которое сообщит вам его состояние.

0
ответ дан 2 December 2019 в 04:25
поделиться

Вы также можете использовать делегаты, если по какой-либо причине вы не можете использовать clausule, вот пример того, как это сделать:

public delegate void TransactionRunner(DbConnection sender, DbTransaction trans, object state);

public void RunTransaction(TransactionRunner runner, object state)
    {
        RunTransaction(runner, IsolationLevel.ReadCommitted, state);
    }

public void RunTransaction(TransactionRunner runner, IsolationLevel il, object state)
    {

        DbConnection cn = GetConnection from pool
        DbTransaction trans = null;

        try
        {  
            trans = cn.BeginTransaction(il);
            runner(cn, trans, state);
            trans.Commit();
        }
        catch (Exception err)
        {
            if (trans != null)
                trans.Rollback();
            throw err;
        }
        finally
        {
            //Here you can close anything that was left open
        }
    }

Затем, когда вам нужно это использовать, просто используйте функцию и передайте функцию как

public void DoStuff(){
    TransactionRunner tr = new TransactionRunner(MyFunction);
    RunTransaction(tr, <a parameter>);
}
public void DoStuffInternal(DbConnection cn, DbTransaction trans, object state){
    //Do Stuff and Im sure that the transaction will commit or rollback
}

Сейчас это кажется излишним в .Net 3.5, но именно так мы поступали тогда в .Net 1.0 ... Надеюсь, это поможет ...

0
ответ дан 2 December 2019 в 04:25
поделиться

Проверить, открыт ли он, и если да, закрыть. Внимание, если вы используете класс SqlHelper, это ошибка - он не закрывает соединение в некоторых сценариях. Решение - использовать в коде try / catch или using блоки, в зависимости от того, до версии 2.0 вы или нет.

0
ответ дан 2 December 2019 в 04:25
поделиться

На вопрос Эрлза никто не ответил. («Почему вы так делаете?» - не ответ.) Я думаю, что ответ заключается в том, что вы не можете определить, есть ли у соединения считыватель открытых данных, просто взглянув на само соединение. Соединение не предоставляет никаких свойств, которые сообщают вам об этом. Открытие соединения устанавливает для его свойства State значение ConnectionState.Open. Открытие на нем средства чтения данных не меняет состояние подключения. Значения состояния, такие как ConnectionState.Fetching, используются только во время выполнения таких операций с данными, как SqlDataReader.Read (). Когда соединение просто существует между чтениями, состояние соединения просто открыто. Таким образом, чтобы определить, когда открытый ридер использует соединение, вы должны проверить состояния читателей, которые могут его использовать.

4
ответ дан 2 December 2019 в 04:25
поделиться

Сегодня я также столкнулся с такой же ситуацией, но ... безуспешно в Интернете.

Итак, я написал приведенный ниже код, чтобы узнать, открывается ли считыватель в соединении или обычно находят, готово ли соединение к использованию:

private bool IsConnectionReady(SqlConnection Connection)
{
    bool nRet = true;

    try
    {
        String sql = "SELECT * FROM dummy_table";

        using (SqlCommand cmd = new SqlCommand(sql, Connection))
        {
            using (SqlDataReader rdr = cmd.ExecuteReader())
            { }
        }
    }
    catch (Exception ex)
    {
        nRet = false;
    }

    return nRet;
}

"dummy_table" - это пустая фиктивная таблица в моей базе данных для проверки доступности.

Это просто обходной путь, но я должен заставить все работать и иметь возможность проверять соединение доступность в любом случае.

Надеюсь, это вам поможет.

0
ответ дан 2 December 2019 в 04:25
поделиться

Согласно статье , вы всегда должны закрывать программу чтения после того, как вы готово, даже если вы используете блок using. Блок using закроет соединение, но не закроет читателя. Почему несогласованность? Бьет меня.

0
ответ дан 2 December 2019 в 04:25
поделиться

, а затем попробуйте запустить другой запрос, используя тот же SqlConnection, тогда он выдаст ошибку.

Конечно, вы можете включить Несколько активных наборов результатов - тогда он не выбрасывает . Конечно, есть некоторые ограничения (не всегда?), Но это сработает. Конечно, это предназначено только для операций вложения . Если проблема в том, что вы случайно оставили что-то открытым (что вы уже должны были закрыть), то ответ (как уже говорилось) с использованием .

1
ответ дан 2 December 2019 в 04:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: