Если мы не можем получить выходные параметры, пока SqlDataReader не будет закрыт, то почему ...? - PullRequest
2 голосов
/ 13 апреля 2010

1)

Пока SqlDataReader используется, связанный SqlConnection занят обслуживанием SqlDataReader, и с SqlConnection нельзя выполнять никакие другие операции, кроме его закрытия. Это происходит до тех пор, пока не будет вызван метод Close SqlDataReader. Например, вы не можете извлечь выходные параметры до тех пор, пока не вызовете Close.

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

    public int Something()
    {
        using (SqlConnection con = new SqlConnection(this.ConnectionString))
        {
            SqlCommand cmd = new SqlCommand("some_procedure", con);
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Add("@ID", SqlDbType.Int).Direction = ParameterDirection.Output;
            con.Open();
            cmd.ExecuteReader();
            return (int)cmd.Parameters["@ID"].Value;
        }
    }

2)

Вы можете сбросить свойство CommandText и повторно использовать объект SqlCommand. Однако вы должны закрыть SqlDataReader, прежде чем сможете выполнить новую или предыдущую команду.

Почему вы должны закрыть sqldatareader перед выполнением новой команды?

1018 * спасибо *

Ответы [ 2 ]

3 голосов
/ 13 апреля 2010

В вашем первом вопросе вы выполняете NonQuery - поэтому нет читателя, который нужно закрыть до получения выходного параметра.

По второму вопросу, вы просто делаете. Команда не позволит вам вызвать другого читателя, пока он открыт.

0 голосов
/ 13 апреля 2010

Прошу прощения за то, что так прямо сформулировал, но у вас, похоже, нет четкого представления о том, что именно представляет собой считыватель данных (System.Data.IDataReader). Итак, позвольте мне продемонстрировать:

using System;
using System.Data;
using System.Data.SqlClient;

string connectionString = "...";

// create and open a DB connection:
using (IDbConnection connection = new SqlConnection(connectionString))
{
    connection.Open();

    // create a command object:
    using (IDbCommand query = connection.CreateCommand())
    {
        query.CommandType = CommandType.Text;
        query.CommandText = "SELECT ID, Name, Birthdate FROM SomeTable";

        // execute the query and retrieve a data reader object:
        using (IDataReader reader = query.ExecuteReader())
        {
            // the data reader is now used to read the query result:
            while (reader.Read())
            {
                int id = reader.GetInt32(0);
                string name = reader.GetString(1);
                DateTime birthdate = reader.GetDateTime(0);
            }
        }

        // at this point, the data reader object has been disposed.
        // the DB connection can now be used again, e.g. by issuing
        // another query:

        command.CommandText = "SELECT COUNT(*) FROM SomeOtherTable";
        ...
    }
}

Примечание: Я воздержался от использования var, поэтому вы точно знаете, какие типы задействованы. (Обратите также внимание на то, что я использую в основном типы интерфейсов, такие как IDbConnection, вместо конкретных классов реализации, таких как SqlConnection. Это делает код более легко адаптируемым для других СУБД.)

Теперь вы можете видеть, что в своем коде вы никогда не использовали устройство чтения данных. Поэтому ваш код работал, потому что никогда не было открытого устройства чтения данных, которое могло бы «заблокировать» ваше соединение с БД.

...