Выполнить хранимую процедуру с параметрами в 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 бросается о том, что мне нужно предоставить 'somethingId'

процедура или функция 'spMyStoredProcedure' ожидает параметр '@somethingId', который не был предоставлен.

мой даль похожа на основе этого проекта на 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 и нажмите Ф5.

кроме того, если ваши параметры фиксированы, я бы предложил просто использовать:

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)

вам нужно будет расширить его для поддержки исходящих параметров и возврата результатов, но он содержит часть для создания динамических параметров 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;
    }

}


поскольку это был лучший результат для меня, но не было ответов, которые имеют дело с 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);
        }
    }