Как выполнить табличную функцию в ado.net?

Я использую адо.нет.

У меня есть функция jsp в моей базе данных, которая принимает 2 параметра и возвращает таблицу. Мне нужно запросить у пользователя два параметра, затем выполнить функцию jsp и вывести таблицу на экран. Вот что у меня есть на данный момент:

jspCmd = new SqlCommand(jspStmt, conn);
jspCmd.CommandType = CommandType.StoredProcedure;

jspCmd.Parameters.Add("@snum", SqlDbType.VarChar, 5);
jspCmd.Parameters.Add("@pnum", SqlDbType.VarChar, 5);
jspCmd.Prepare();

Console.WriteLine();
Console.WriteLine(@"Please enter S# and P# separated by blanks, or exit to terminate");
string line = Console.ReadLine();
Regex r = new Regex("[ ]+");
string[] fields = r.Split(line);

if (fields[0] == "exit") break;
jspCmd.Parameters[0].Value = fields[0];
jspCmd.Parameters[1].Value = fields[1];

jspCmd.ExecuteNonQuery();//<---I BELIEVE ERROR COMING FROM HERE

reader = jspCmd.ExecuteReader();//PRINT TABLE TO SCREEN
while (reader.Read())
{
    Console.WriteLine(reader[0].ToString() + "  "
                      + reader[1].ToString()
                      + "  " + reader[2].ToString());
}
reader.Close();

Когда я запускаю это, я ввожу два параметра, и возникает исключение:

Program aborted: System.Data.SqlClient.SqlException (0x80131904): The request
for procedure 'jsp' failed because 'jsp' is a table valued function object.

Может ли кто-нибудь показать мне правильный способ сделать это?


person Reeggiie    schedule 27.03.2014    source источник


Ответы (3)


Убедитесь, что ваш jspStmt является SELECT с обычной привязкой параметров, например:

var jspStmt = "SELECT * FROM myfunction(@snum, @pnum)";
// this is how table-valued functions are invoked normally in SQL.

Опустите следующее:

jspCmd.CommandType = CommandType.StoredProcedure; 
// WRONG TYPE, leave it as CommandType.Text;

Опустите следующее:

jspCmd.ExecuteNonQuery();//<---I BELIEVE ERROR COMING FROM HERE
// WRONG KIND OF RESULT, it **IS** a query.  Further, let your
// later jspCmd.ExecuteReader() invoke it and get the actual data.
person David Bullock    schedule 17.02.2015

Чтобы выполнить табличную функцию, используйте SELECT в качестве текстовой команды:

jspCmd = new SqlCommand("SELECT * FROM " + jspStmt + "()", conn);
jspCmd.CommandType = CommandType.Text;

И чтобы получить результаты, используйте ExecuteReader, что вы уже делаете, но после вы используете ExecuteNonQuery, то есть для INSERTs, UPDATEs и т. д.

person D Stanley    schedule 27.03.2014
comment
Я попробовал это, и я получаю новое исключение. Мой jspStmt = jsp, потому что это имя функции. И исключение: программа прервана: System.Data.SqlClient.SqlException (0x80131904): недопустимое имя столбца «jsp». Выписка(я) не может быть подготовлена. - person Reeggiie; 28.03.2014
comment
@ user3345200 тоже забыл добавить скобки - попробуйте сейчас. - person D Stanley; 28.03.2014
comment
Я добавил ( ), и теперь он изменился на: Программа прервана: System.Data.SqlClient.SqlException (0x80131904): «jsp» не является распознанным именем встроенной функции. Выписка(я) не может быть подготовлена. ----jsp находится в моей папке процедур для моей базы данных. Любая идея, почему это дало бы мне это? - person Reeggiie; 28.03.2014
comment
Я настоятельно рекомендую вам упростить вещи. Используйте студию управления SQL Server для создания действительного запроса SELECT для этой функции. Что-то вроде SELECT * FROM dbo.jsp() или SELECT * FROM dbo.jsp(1, 'string', '2014-03-29'). Затем поработайте над созданием того же запроса в своем коде. - person John Saunders; 30.03.2014

Чтобы добавить к ответу Д. Стэнли, похоже, что новые исключения, которые вы получаете, связаны с неправильным вызовом функции. Попробуйте следующее (исправлен оператор select и добавлены параметры в функцию):

jspCmd = new SqlCommand("SELECT * FROM jsp('" + fields[0] + "', '" + fields[1] + "')", conn);

Затем продолжайте использовать ExecuteReader, как вы это делали.

person EthanolMighty    schedule 30.03.2014
comment
Это небезопасно. Неправильно параметризуя оператор SQL, вы рискуете атакой с внедрением SQL. Смотрите ответ Дэвида Буллока для правильного примера. - person David; 01.02.2018