Могу ли я использовать DynamicParameters с шаблоном и иметь возвращаемый параметр в dapper? - PullRequest
4 голосов
/ 04 ноября 2011

Система, над которой я сейчас работаю, использует хранимые процедуры для доступа ко всем данным.Сейчас я изучаю Dapper (пока он выглядит великолепно), но мне было интересно, могу ли я использовать объект DynamicParameters, созданный с использованием Template, но сделать один из параметров выходным параметром.Например:

SP:

CREATE PROCEDURE InsertPerson
  @ID int Output,
  @Name varchar(100),
  @DOB DateTime2
AS
--INSERT STATEMENT

SET @ID = SCOPE_IDENTITY()

POCO:

internal class Person
{
  public int ID { get; set; }
  public string Name { get; set; }
  public DateTime DOB { get; set; }
}

Код:

var procParams = new DynamicParameters(person);
connection.Execute("InsertPerson", procParams, commandType: CommandType.StoredProcedure);

// This is where i'm having the issue, can it be done?
person.ID = procParams.Get<int>("ID");

Текущий Я получаю ошибку, потому что ключне был найден.Есть ли способ получить параметр вывода идентификатора, не устанавливая вручную все параметры сохраненных процедур?

Ответы [ 2 ]

7 голосов
/ 05 ноября 2011

С помощью быстрой настройки Add сейчас заменяет значение из шаблона, позволяя:

public void TestProcWithOutParameter()
{
    connection.Execute(
        @"CREATE PROCEDURE #TestProcWithOutParameter
@ID int output,
@Foo varchar(100),
@Bar int
AS
SET @ID = @Bar + LEN(@Foo)");
    var obj = new
    { // this could be a Person instance etc
        ID = 0,
        Foo = "abc",
        Bar = 4
    };
    var args = new DynamicParameters(obj);
    args.Add("ID", 0, direction: ParameterDirection.Output);
    connection.Execute("#TestProcWithOutParameter", args,
                 commandType: CommandType.StoredProcedure);
    args.Get<int>("ID").IsEqualTo(7);
}

Это достаточно близко? Вы также можете использовать ParameterDirection.ReturnValue из ранее существовавшего или нового значения. Обратите внимание, что не обновляется непосредственно обратно в исходный шаблон; значение должно быть получено из экземпляра DynamicParameters (как показано).

2 голосов
/ 04 ноября 2011

Когда вы используете конструктор для DynamicParameters, чтобы указать объект шаблона, вам все равно нужно будет указать, что @ID является выходным параметром.Сначала через шаблон он будет установлен на ParameterDirection.Input.Как только вы добавите его, он будет переопределен, чтобы иметь обновленные значения, тогда вы можете получить значение по имени параметра следующим образом:

procParams.Add("@ID", dbType: DbType.Int32, direction: ParameterDirection.Output);
// ... execute ...
person.ID = procParams.Get<int>("@ID");

Я смог заставить это работать и использовал ваши классы и кодВ дополнение к тому, что я показал выше.

EDIT: , как обсуждалось в комментариях, хранимая процедура не принимает больше аргументов, чем она объявила.Таким образом, альтернативный подход заключается в отказе от хранимой процедуры и использовании некоторого встроенного SQL.При использовании запроса Dapper будет игнорировать любые заданные ему параметры, которые не указаны в операторе SQL.Это обходной путь для решения этой проблемы:

string sql = "INSERT INTO Person (Name, DOB) VALUES (@Name, @DOB) SELECT SCOPE_IDENTITY()";
decimal id = conn.Query<decimal>(sql, procParams).First();
person.ID = (int)id;

Обратите внимание, что SCOPE_IDENTITY() возвращает десятичное число, а не целое число.

Другая идея, которая, на мой взгляд, не идеальна,изменить код Dapper и добавить метод Remove в класс DynamicParameters для удаления нежелательных параметров.Это не сильно вас экономит, поскольку вы все равно будете тратить время на указание параметров, которые нужно удалить, чтобы сделать хранимую процедуру счастливой.Если вы решите реализовать это, помните, что регистр имеет значение при указании ключа для удаления из словаря parameters.

...