У хрупкой хранимой процедуры слишком много аргументов, указанных при передаче IEnumerable ей - PullRequest
3 голосов
/ 12 января 2020

Я вызываю свою процедуру следующим способом:

public async Task<IEnumerable<Algorithm>> GetAlgorithmsByNameAsync(IEnumerable<string> names)
{
    var parameters = new DynamicParameters();
    parameters.Add("@names", names);

    var connection = _connection.GetOpenConnection();   
    return await connection.QueryAsync<Algorithm>("GetAlgorithmsByName", parameters, commandType: CommandType.StoredProcedure);
}

Моя процедура выглядит следующим образом:

CREATE TYPE [dbo].[StringList] AS TABLE(
    [Item] [NVARCHAR](MAX) NULL
);

--PROCEDURE HERE--

CREATE PROCEDURE GetAlgorithmsByName

@names StringList READONLY -- my own type

AS
BEGIN
    SELECT ALgorithmId, Name From Algorithms WHERE Name IN (SELECT Item FROM @names)
END

Из приведенного выше кода я получаю ошибку:

"В процедуре или функции GetAlgorithmsByName указано слишком много аргументов."

Что я делаю не так? Как передать IEnumerable<string> хранимой процедуре с помощью dapper?

Ответы [ 3 ]

3 голосов
/ 12 января 2020

Табличные параметры не являются тривиальными для использования; Одним из способов является использование метода расширения, который Dapper добавляет к DataTable (что-то вроде AsTableValuedParameter), но: он не работает так просто, как IEnumerable<T> - по крайней мере, не сегодня. Вам также, вероятно, здесь не нужно DynamicParameters.

Если вам нужен просто набор строк, то один очень практичный вариант c - это посмотреть на встроенный string_split API в SQL Сервер, если вы можете определить токен-разделитель, который никогда не используется в данных. Затем вы можете просто передать одну строку с разделителями.

1 голос
/ 12 января 2020

В вашей хранимой процедуре ожидается [Item] [NVARCHAR](MAX), это означает один элемент, в то время как вы передаете IEnumerable<string> names. Вот почему вы получаете сообщение об ошибке.

Существует множество способов передачи списка строк в sp

  1. XML
  2. Использование табличные параметры как CREATE TYPE NameList AS TABLE ( Name Varchar(100) );
  3. Используя names = "Name1, Name2, .. , Namen"; затем sql, вы можете использовать T- SQL split string , чтобы получить список имен

Обновлено Вы передаете параметр неправильно, давайте исправим это таким образом

     using (var table = new DataTable()) 
     {
      table.Columns.Add("Item", typeof(string));

      for (int i = 0; i < names.length; i++)
        table.Rows.Add(i.ToString());

      var pList = new SqlParameter("@names", SqlDbType.Structured);
      pList.TypeName = "dbo.StringList";
      pList.Value = table;

      parameters.Add(pList);
   }
0 голосов
/ 12 января 2020

Вы можете использовать IEnumerable (Dynami c) вместо IEnumerable (string).

Проверьте эту ссылку и попробуйте Как реализовать IEnumerable (Dynami c)

...