Выполнить хранимую процедуру с параметрами в Dapper
Я использую Dapper (спасибо Сэм, отличный проект.) Микро ORM с DAL и по какой-то причине я не могу выполнять хранимые процедуры с входными параметрами.
В определенной службе у меня есть что-то вроде этого:
public void GetSomething(int somethingId)
{
IRepository<Something, SomethingEnum> repository = UnitOfWork.GetRepository<Something, SomethingEnum>();
var param = new DynamicParameters();
param.Add("@somethingId", dbType: DbType.Int32, value:somethingId, direction: ParameterDirection.Input);
var result = repository.Exec<Something>(SomethingEnum.spMyStoredProcedure, param);
...
}
Когда происходит выполнение хранимой процедуры, создается исключение SqlException, в котором говорится, что мне нужно предоставить'thingId '
Процедура или функция spMyStoredProcedure ожидает параметр @somethingId, который не был предоставлен.
Мой DAL похож на этот GitHub проект Pencroff.
Я что-то здесь упускаю?
Обновление: я фактически передаю commandType через SomethingEnum:
public class SomethingEnum : EnumBase<SomethingEnum, string>
{
public static readonly SomethingEnum spMyStoredProcedure = new SomethingEnum("spMyStoredProcedure", "[dbo].[spMyStoredProcedure]", CommandType.StoredProcedure);
public SomethingEnum(string Name, string EnumValue, CommandType? cmdType): base(Name, EnumValue, cmdType)
{
}
}
4 ответа
Вам нужно указать тип команды: убедитесь, что commandType: CommandType.StoredProcedure
в щегольском звонке. В противном случае это просто выполнение текстовой команды:
spMyStoredProcedure
(с некоторыми неиспользованными параметрами в окружающем контексте). Это законный TSQL, и попытки вызова spMyStoredProcedure
без передачи параметров - так же, как если бы вы положили spMyStoredProcedure
в SSMS и нажмите f5.
Кроме того, если ваши параметры фиксированы, я бы на самом деле предложил просто использовать:
var param = new { somethingId };
или даже просто вставьте это полностью:
var result = repository.Exec<Something>(SomethingEnum.spMyStoredProcedure,
new { somethingId }, commandType: CommandType.StoredProcedure);
(примечание: если ваш Exec<T>
метод только когда-либо обрабатывает хранимые процедуры, вы можете переместить commandType
внутренний для метода - или вы можете сделать его необязательным параметром по умолчанию CommandType.StoredProcedure
)
var queryParameters = new DynamicParameters();
queryParameters.Add("@parameter1", valueOfparameter1);
queryParameters.Add("@parameter2", valueOfparameter2);
await db.QueryAsync<YourReturnType>(
"{NameOfStoredProcedure}",
queryParameters,
commandType: CommandType.StoredProcedure)
Поскольку это был лучший результат для меня, но не было ответов, которые касаются ExecuteNonQuery с табличными параметрами, вот код для этого:
var queryParameters = new DynamicParameters();
queryParameters.Add("@Param0", datatable0.AsTableValuedParameter());
queryParameters.Add("@Param1", datatable1.AsTableValuedParameter());
var result = await ExecuteStoredProc("usp_InsertUpdateTest", queryParameters);
private async Task<Result<int>> ExecuteStoredProc(string sqlStatement, DynamicParameters parameters)
{
try
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
await conn.OpenAsync();
var affectedRows = await conn.ExecuteAsync(
sql: sqlStatement,
param: parameters,
commandType: CommandType.StoredProcedure);
return Result.Ok(affectedRows);
}
}
catch (Exception e)
{
//do logging
return Result.Fail<int>(e.Message);
}
}
Вам нужно будет расширить его для поддержки исходящих параметров и возврата результатов, но он содержит часть для создания динамических параметров Dapper.
internal static bool ExecuteProc(string sql, List<SqlParameter> paramList = null)
{
try
{
using (SqlConnection conn = new SqlConnection (GetConnectionString()))
{
DynamicParameters dp = new DynamicParameters();
if(paramList != null)
foreach (SqlParameter sp in paramList)
dp.Add(sp.ParameterName, sp.SqlValue, sp.DbType);
conn.Open();
return conn.Execute(sql, dp, commandType: CommandType.StoredProcedure) > 0;
}
}
catch (Exception e)
{
//do logging
return false;
}
}
Это работает для меня. Обратите внимание, что метод, делающий это, является асинхронным, следовательно, await и QueryAsync. Также обратите внимание, что создается анонимный тип, чтобы упростить отправку параметра "Id".
await dbConnection.QueryAsync<Something>("StoredProcedureNameGoesHere @Id", new { Id = id });