简体   繁体   English

在Dapper中执行带有参数的存储过程

[英]Execute stored procedure w/parameters in Dapper

I'm using Dapper (thanks Sam , great project.) a micro ORM with a DAL and by some reason I'm not able to execute stored procedures with input parameters. 我正在使用Dapper (感谢Sam ,很棒的项目。)带有DAL的微型ORM,由于某种原因,我无法使用输入参数执行存储过程。

In a example service I've the following code: 在示例服务中,我有以下代码:

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);

    ...

}

When the execution of the stored procedure is triggered a SqlException is thrown stating that I need to provide the 'somethingId' 当触发执行存储过程时,抛出SqlException声明我需要提供'somethingId'

Procedure or function 'spMyStoredProcedure' expects parameter '@somethingId', which was not supplied. 过程或函数'spMyStoredProcedure'需要参数'@somethingId',这是未提供的。

My DAL is similar based on this github project of Pencroff. 我的DAL类似于Pencroff的这个github项目。

Am I missing something here? 我在这里错过了什么吗?

Update: I am actually passing the commandType via the SomethingEnum: 更新:我实际上是通过SomethingEnum传递commandType:

 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)
    {
    }
}

You need to tell it the command type: make sure there's a commandType: CommandType.StoredProcedure in the dapper call. 你需要告诉它命令类型:确保在dapper调用中有一个commandType: CommandType.StoredProcedure Otherwise, it is simply executing the text command: 否则,它只是执行text命令:

spMyStoredProcedure

(with some unused parameters in the ambient context). (在环境上下文中有一些未使用的参数)。 This is legal TSQL, and attempts to call spMyStoredProcedure without passing parameters - the same as if you put spMyStoredProcedure into SSMS and press f5 . 这是合法的TSQL,并尝试在不传递参数的情况下调用spMyStoredProcedure - 就像将spMyStoredProcedure放入SSMS并按f5一样

Also, if your parameters are fixed, I would actually suggest just using: 此外,如果您的参数是固定的,我实际上建议只使用:

var param = new { somethingId };

or even just inline it completely: 甚至只是完全内联它:

var result = repository.Exec<Something>(SomethingEnum.spMyStoredProcedure,
    new { somethingId }, commandType: CommandType.StoredProcedure);

(note: if your Exec<T> method only ever handles stored procedures, you could move the commandType internal to the method - or you could make it an optional parameter that defaults to 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)

Since this was the top result for me, but there were no answers that deal with ExecuteNonQuery with table valued parameters, here is the code for that: 因为这对我来说是最好的结果,但是没有用表值参数处理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);
        }
    }

You'll need to extend it to support outbound parameters and returning results, but it contains the portion for creating the Dapper dynamic parameters. 您需要扩展它以支持出站参数和返回结果,但它包含用于创建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;
    }

} }

This works for me. 这适合我。 Note that the method doing this is async, hence the await and QueryAsync. 请注意,执行此操作的方法是异步的,因此await和QueryAsync。 Also notice that an anonymous type is created to facilitate the 'Id' parameter being sent. 另请注意,创建了匿名类型以便于发送“Id”参数。

await dbConnection.QueryAsync<Something>("StoredProcedureNameGoesHere @Id", new { Id = id });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM