Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用存储过程从Dapper.net查询返回值_C#_Sql Server_Dapper - Fatal编程技术网

C# 使用存储过程从Dapper.net查询返回值

C# 使用存储过程从Dapper.net查询返回值,c#,sql-server,dapper,C#,Sql Server,Dapper,我试图使用Dapper.Net调用存储过程,并获取返回值 p.Add("@INCIDENT_ID", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue); var retResults = con.Execute("usp_GetIncidentID", p, commandType:CommandType.StoredProcedure); int IncidentID = p.Get<int>("I

我试图使用Dapper.Net调用存储过程
,并获取返回值

p.Add("@INCIDENT_ID", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);

var retResults = con.Execute("usp_GetIncidentID", p, commandType:CommandType.StoredProcedure);

int IncidentID = p.Get<int>("INCIDENT_ID"); 
我怀疑(未测试)这纯粹是命名参数的方式不匹配;尝试(注意已删除的
@
):

p.Add(“事件ID”,dbType:dbType.Int32,方向:ParameterDirection.ReturnValue);
var retResults=con.Execute(“usp_GetIncidentID”,p,commandType:commandType.storedProcess);
int IncidentID=p.Get(“事件ID”);

您可以读取如下值

var incidentId = retResults.ToList()[0].INCIDENT_ID; 

我在阅读查询结果时遇到了类似的问题。对Read()的第一个调用返回了正确的类型,第二个调用返回了DapperRow。我发现使用Read()的类型化版本:

var lineExists=query.Read().FirstOrDefault()=1;

解决了我的问题。

为了简单起见,我把它删减了。我使用输出参数,因为这使我能够完全控制传回的数据类型。我可以将此方法用于任何其他场景,而不仅仅是插入

存储过程:

ALTER PROCEDURE User_Insert (
@EmailAddress nvarchar(255),
@Id bigint OUT
) AS
INSERT INTO User (
        [EmailAddress]
    ) VALUES (
        @EmailAddress
    )
    set @Id = SCOPE_IDENTITY()
响应代码:

var sql = "Execute User_Insert @EmailAddress, @Id = @Id OUTPUT";
var _params = new DynamicParameters();
_params.Add("EmailAddress", user.EmailAddress);
_params.Add("Id", dbType: DbType.Int64, direction: ParameterDirection.Output);

using (var connection = new SqlConnection(ConnectionString)) {
    connection.Open();
    using (var transaction = connection.BeginTransaction()) {
        var result = SqlMapper.Execute(connection, sql, param, transaction);
        transaction.Commit();
    }
}    
var id = _params.Get<long>("Id");
var sql=“执行用户\u插入@EmailAddress,@Id=@Id输出”;
var _params=新的动态参数();
_参数Add(“EmailAddress”,user.EmailAddress);
_Add(“Id”,dbType:dbType.Int64,direction:ParameterDirection.Output);
使用(var连接=新的SqlConnection(ConnectionString)){
connection.Open();
使用(var transaction=connection.BeginTransaction()){
var result=SqlMapper.Execute(连接、sql、参数、事务);
Commit();
}
}    
var id=_params.Get(“id”);

使用Dapper的测试版本,我发现这就像一个魅力:

result = dbConnection.ExecuteScalar<int>(typeof(UCCCCException).Name + "_c",
                        obj, commandType: CommandType.StoredProcedure);
需要注意的是,您必须为正在使用的类中的每个属性指定一个条目作为存储过程的参数,即使这些属性在目标表中不存在。如果在MVC情况下有许多字段是视图字段,那么这可能会很烦人

要获取返回值,只需使用Execute,并确保存储过程中的最后一条语句是Select@@Identity

它工作得非常好,允许我在存储库中编写一个通用的insert命令,如下所示:

ALTER PROCEDURE [dbo].[UCCCCException_c]
(
@Id int = null,
@ExceptionDate datetime = null,
@HResult int = 0,
@Message varchar(8000) = null,
@Source varchar(8000) = null,
@StackTrace varchar(8000) = null,
@Module varchar(8000) = null,
@Name varchar(8000) = null,
@created_at datetime = null,
@updated_at datetime = null,
@created_by int = null,
@updated_by int = null
,
@Creator varchar(255) = null,
@Updator varchar(255) = null
)
AS

-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

Insert into dbo.uccccexceptions ( ExceptionDate, HResult, [Message], [Source], StackTrace, Module, Name)
                            values (
                                    coalesce(@ExceptionDate,getdate()),
                                    @HResult,
                                    @Message,
                                    @Source,
                                    @StackTrace,
                                    @Module,
                                    @Name
                                    )
                                    ;
select @@Identity;
go
        public virtual int Insert(T obj)
    {
        int result = -2;
        if (!databaseOnline)
        {
            throw new Exception(HttpStatusCode.ServiceUnavailable.ToString());
        }
        if (obj != null)
        {
            try
            {
                using (IDbConnection dbConnection = ConnectionProvider.OpenConnection())
                {
                    dbConnection.Open();
                    result = dbConnection.ExecuteScalar<int>(typeof(T).Name + "_c",
                        obj, commandType: CommandType.StoredProcedure);
                }
            }
            catch (SqlException sqlex)
            {
                Logger.LogError(sqlex, false);
                throw;
            }
            catch (Exception ex)
            {
                Logger.LogError(ex);
                throw;
            }
        }
        return result;
    }
公共虚拟整数插入(T obj)
{
int结果=-2;
如果(!databaseOnline)
{
抛出新异常(HttpStatusCode.ServiceUnavailable.ToString());
}
如果(obj!=null)
{
尝试
{
使用(IDbConnection dbConnection=ConnectionProvider.OpenConnection())
{
dbConnection.Open();
结果=dbConnection.ExecuteScalar(typeof(T).Name+“\u c”,
obj,commandType:commandType.StoredProcess);
}
}
捕获(SqlException sqlex)
{
Logger.LogError(sqlex,false);
投掷;
}
捕获(例外情况除外)
{
Logger.LogError(ex);
投掷;
}
}
返回结果;
}
我在数据库中使用的约定是,存储过程的名称是类型名称,后跟“\u s”表示选择“\u c”表示插入“\u d”表示删除“\u”表示更新


PS:我讨厌使用Dapper的DynamicParameters或任何其他设备,这些设备要求您对通用存储库中的每个类使用不同的插入或更新方法。

DynamicParameters解决方案对我来说并不干净。最好让存储过程代码返回一个整数(选择1;),并使用dapper
ExecuteScalar(“[sp_name]”,params)

你是什么意思
我无法按照文档中描述的方式访问这些值
你是否尝试过
var IncidentID=con.Query(“usp_GetIncidentID”,commandType:commandType.StoredProcedure).SingleOrDefault()?这是最简单的,如果您的存储过程通过一个“select”返回值就可以了。刚刚尝试过,我得到了{DapperRow,INCIDENT_ID='902306',我以前看到过,但是在尝试访问该值时遇到了问题。DJ Kraze,我编辑了我的问题以参考文档,谢谢!我正在尝试同样的方法,并收到一个“指定的强制转换无效”。我的返回值是SCOPE_IDENTITY(),它应该返回一个bigint,因为这是主键字段。我将我的参数声明为DbType.Int64,可以使用long值调用get作为泛型参数,但这不起作用。由于某些原因,SCOPE_标识继续以int返回。非常令人沮丧。如果你有什么想法,我会非常感激的。马克,我玩过“@”这个符号,我在某个地方读到过,它起了作用,但没有。我得到了正确的值,因为我可以查看“监视”窗口并查看结果中的值。我只是不完全确定如何以“正确”的方式得到它们。retResults={DapperRow,事件ID='902479'}感谢您的回复!结果是否在数据网格中?这个问题表明你在更新参数……马克,是的,这就是结果。根据我对文档的理解,应该将值作为返回类型为“ParameterDirection.ReturnValue”的参数传入。结果返回正确,我只是无法使用“p.get”(“事件ID”)映射到这些结果.这就是我没有得到的部分,为什么我无法从dynamicParameter中获得正确的值。再次感谢您的响应,非常感谢。当您尝试获取返回值时,如果结果集为空,则返回值为空,则该操作无效!如果结果集为0行,而您有返回值,该怎么办?
result = dbConnection.ExecuteScalar<int>(typeof(UCCCCException).Name + "_c",
                        obj, commandType: CommandType.StoredProcedure);
ALTER PROCEDURE [dbo].[UCCCCException_c]
(
@Id int = null,
@ExceptionDate datetime = null,
@HResult int = 0,
@Message varchar(8000) = null,
@Source varchar(8000) = null,
@StackTrace varchar(8000) = null,
@Module varchar(8000) = null,
@Name varchar(8000) = null,
@created_at datetime = null,
@updated_at datetime = null,
@created_by int = null,
@updated_by int = null
,
@Creator varchar(255) = null,
@Updator varchar(255) = null
)
AS

-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

Insert into dbo.uccccexceptions ( ExceptionDate, HResult, [Message], [Source], StackTrace, Module, Name)
                            values (
                                    coalesce(@ExceptionDate,getdate()),
                                    @HResult,
                                    @Message,
                                    @Source,
                                    @StackTrace,
                                    @Module,
                                    @Name
                                    )
                                    ;
select @@Identity;
go
        public virtual int Insert(T obj)
    {
        int result = -2;
        if (!databaseOnline)
        {
            throw new Exception(HttpStatusCode.ServiceUnavailable.ToString());
        }
        if (obj != null)
        {
            try
            {
                using (IDbConnection dbConnection = ConnectionProvider.OpenConnection())
                {
                    dbConnection.Open();
                    result = dbConnection.ExecuteScalar<int>(typeof(T).Name + "_c",
                        obj, commandType: CommandType.StoredProcedure);
                }
            }
            catch (SqlException sqlex)
            {
                Logger.LogError(sqlex, false);
                throw;
            }
            catch (Exception ex)
            {
                Logger.LogError(ex);
                throw;
            }
        }
        return result;
    }