Попытка загрузить второй набор результатов из хранимой процедуры

У меня есть клиентская установка, в которой для возврата данных из базы данных SQL Server используются хранимые процедуры.

Все эти хранимые процедуры построены одинаково — они принимают кучу входных параметров и возвращают:

  • первый - это просто одна строка, один столбец с кодом результата (тип INT) - 0 для успеха, в противном случае некоторые другие значения; если значение равно 0, то есть второй результирующий набор, содержащий фактические данные

  • второй результирующий набор может быть любым - любое количество столбцов и строк

Я пытаюсь создать «общий» способ взаимодействия с этой системой, и моя попытка такова:

  • создать класс, который принимает имя хранимой процедуры и входные параметры
  • возвращаемый тип, который содержит как свойство ErrorCode INT, так и свойство DataTable results

Однако у меня возникли проблемы с тем, чтобы это работало с ADO.NET и SQL Server 2008 R2.

Мой код сводится к следующему:

public MyResultType CallService(string procedureName, MyParameters parameters)
{
     MyResultType result = new MyResultType { ErrorCode = 0 };

     using (SqlConnection conn = new SqlConnection(_connectionString))
     using (SqlCommand cmd = new SqlCommand(procedureName, conn))
     {
         cmd.CommandType = CommandType.StoredProcedure;
         SetupParameters(cmd, parameters);

         // open connection, execute the stored procedure
         conn.Open();

         using (SqlDataReader rdr = cmd.ExecuteReader())
         {
             // get the first result set - the status code, one row, one column of type INT
             while (rdr.Read())
             {
                 result.ErrorCode = rdr.GetInt32(0);
             }

             // if we got a "0" (success) -> go to the next result set and load it into the table
             if(result.ErrorCode == 0 && rdr.NextResult())
             {
                 result.ResultTable = new DataTable();
                 result.ResultTable.Load(rdr);

                 int colCount = result.ResultTable.Columns.Count;
                 int rowCount = result.ResultTable.Rows.Count;
              }

              rdr.Close();
         }

         conn.Close();
   }

   return result;
}

Моя проблема: вызов хранимой процедуры работает нормально, код ошибки = 0 подхватывается просто отлично, таблица данных создается, а количество столбцов соответствует ожидаемому значению, но NO ROWS загружен...

Я пробовал все, что мог, чтобы получить эти строки в DataTable - не повезло. И, конечно же, если я выполняю ту же самую хранимую процедуру в SQL Server Management Studio, все работает просто отлично, я получаю свой ErrorCode=0 и результирующий набор из 18 столбцов и 5 строк - никаких проблем....

Что мне не хватает? Может ли кто-нибудь обнаружить проблему в моем коде? Почему не загружаются строки второго набора результатов (но столбцы, кажется, обнаруживаются)?


person marc_s    schedule 02.12.2012    source источник
comment
Тот факт, что количество столбцов является ожидаемым значением, а таблица результатов создана надлежащим образом (за исключением отсутствия строк), предполагает, что существует некоторая разница в том, как хранимая процедура вызывается из консоли (SQL Server Management Studio) и из вашего ADO. Чистый код. В частности, какие аргументы принимает хранимая процедура? Вы ссылаетесь, не раскрывая их как параметры во фрагменте кода выше.   -  person hardmath    schedule 02.12.2012
comment
Должна быть возможность проверить это, запустив трассировку профилировщика.   -  person Tom Hunter    schedule 02.12.2012


Ответы (2)


Опубликованный код работает нормально - была разница между тем, как я называю его из С#, и в SQL Server Management Studio: обработка NULL.

У меня были некоторые входные параметры, установленные на int, и, таким образом, я предоставил хранимой процедуре значение 0, в то время как он действительно ожидал получить NULL, если значение не определено......

Глупая ошибка новичка..... ИЗВИНИТЕ, РЕБЯТА! И спасибо за ваш вклад!

person marc_s    schedule 02.12.2012

Метод DataTable.Load неявно вызывает метод NextResult, поэтому в сочетании с вашим явным вызовом он переходит к набору результатов, которого там нет. Вам следует удалить свой собственный вызов NextResult, если вы хотите использовать DataTable.Load или в цикле и заполнить таблицу данных самостоятельно.

person Mendhak    schedule 02.12.2012
comment
DataTable.Load вызывает NextResult после загрузки своего результирующего набора.... если я не помещу туда .NextResult(), то я снова загружу первый результирующий набор (только одну строку, один столбец). я это уже проверял - person marc_s; 02.12.2012