Таблица кратных значений в DataReader

Я обычно использую DataSet, т.к. он очень гибкий. Недавно мне поручили задачу оптимизации кода. Чтобы уменьшить количество попаданий в базу данных, я меняю два запроса в процедуре. один запрос возвращает count, а другой возвращает actual data. То есть My stored procedure возвращает две таблицы. Теперь я знаю, как читать обе таблицы, используя DataSets, но мне нужно читать обе таблицы, используя DataReader. В поисках этого я нашел Это.

Я следую статье и написал свой код следующим образом:

dr = cmd.ExecuteReader();
while (dr.Read())
{


}
if (dr.NextResult()) // this line throws exception
{
   while (dr.Read())
{

Но я получаю исключение в dt.NextResult. Исключение:

Invalid attempt to call NextResult when reader is closed.

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


person muhammad kashif    schedule 19.10.2012    source источник
comment
Чего я не понимаю: один запрос возвращает количество, а другой возвращает фактические данные. То есть моя хранимая процедура возвращает две таблицы. Почему число (которое является скалярным значением) представляет собой таблицу?   -  person Tim Schmelter    schedule 19.10.2012
comment
Да, это скалярное значение, но хранимая процедура написана с использованием динамических запросов. оба запроса очень большие, и запросы записываются как varchar, а затем, в конце концов, выполняются с использованием Exec. Если я вызываю запрос Count в качестве подзапроса фактического запроса данных, размер переменной запроса очень велик, и он выполняется с ошибками. Поэтому, чтобы избежать этого, я написал два разных запроса, поэтому Count также поступает из таблицы (вторая таблица). Надеюсь, я ясно дал понять.   -  person muhammad kashif    schedule 19.10.2012


Ответы (3)


Попробуйте это, потому что это закроет соединение, считыватель данных и команду после завершения задачи, так что это не приведет к исключению закрытия считывателя данных.

Также проверьте, как это if(reader.NextResult()), чтобы проверить, есть ли следующий результат,

using (SqlConnection connection = new SqlConnection("connection string here"))
{
    using (SqlCommand command = new SqlCommand
           ("SELECT Column1 FROM Table1; SELECT Column2 FROM Table2", connection))
    {
        connection.Open(); 
        using (SqlDataReader reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
                MessageBox.Show(reader.GetString(0), "Table1.Column1");
            }

            if(reader.NextResult())
            {
               while (reader.Read())
              {
                MessageBox.Show(reader.GetString(0), "Table2.Column2");
              }
            }
        }
    }
}
person Pranay Rana    schedule 19.10.2012
comment
@muhammadkashif - ваша ошибка вызвана тем, что либо ваше соединение закрыто, либо устройство чтения данных закрыто, поэтому лучше проверить это также, как это .... также проверьте следующий набор результатов в предложении if, как я сделал, что также помогает вам .... - person Pranay Rana; 19.10.2012
comment
Спасибо, я пропустил {} после использования, из-за чего только первое время считалось частью оператора Using. Спасибо, ваш ответ будет отмечен как принятый через пять минут. - person muhammad kashif; 19.10.2012
comment
@muhammadkashif, не могли бы вы обновить свой вопрос, чтобы показать, как у вас была неправильная конструкция using …;? Это внесло бы ясность в вопрос… - person binki; 01.07.2015
comment
@Pranay Rana, я возвращаю 4-ю таблицу, так как я могу взять данные из данных 3-й и 4-й таблиц с помощью вашего решения, не могли бы вы мне помочь ?? - person coderwill; 08.05.2017

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

Вот мой тестовый код:

using (var con = new SqlConnection(Properties.Settings.Default.ConnectionString))
{
    using (var cmd = new SqlCommand("SELECT TOP 10 * FROM tabData; SELECT TOP 10 * FROM tabDataDetail;", con))
    {
        int rowCount = 0;
        con.Open();
        using (IDataReader rdr = cmd.ExecuteReader())
        {
            while (rdr.Read())
            {
                String object1 = String.Format("Object 1 in Row {0}: '{1}'", ++rowCount, rdr[0]);
            }
            if (rdr.NextResult())
            {
                rowCount = 0;
                while (rdr.Read())
                {
                    String object1 = String.Format("Object 1 in Row {0}: '{1}'", ++rowCount, rdr[0]);
                }
            }
        }
    }
}
person Tim Schmelter    schedule 19.10.2012
comment
Спасибо, моя проблема решена, голосую за ваши усилия. - person muhammad kashif; 19.10.2012
comment
Если я хочу использовать DataTable.Load() вместо зацикливания считывателя, то заполняется вторая таблица. Любая подсказка по этому поводу? - person Biki; 13.06.2016
comment
Наконец я получил ключ. Если мы используем DataTable.Load(), то нам не нужно использовать rdr.NextResult(), так как это делается неявно. - person Biki; 14.06.2016

Я построил ответ Pranay Rana, потому что мне нравится, чтобы он был как можно меньше.

string rslt = "";
using (SqlDataReader dr = cmd.ExecuteReader())
{
    do
    {
        while (dr.Read())
        {
            rslt += $"ReqID: {dr["REQ_NR"]}, Shpr: {dr["SHPR_NR"]}, MultiLoc: {dr["MULTI_LOC"]}\r\n";
        }
    } while (dr.NextResult());
}
person tolsen64    schedule 26.08.2019