2012-09-09 65 views
7

这里是我的存储过程。当我测试它时,总是得到正确的结果。使用Dapper.net调用存储过程,总是返回-1回

ALTER PROCEDURE [dbo].[AddSmoothieIngredients] 
    -- Add the parameters for the stored procedure here 
    @Query NVARCHAR(4000) , 
    @SmoothieId INT , 
    @CreatedDate DATETIME , 
    @Status INT , 
    @UserId INT 
AS 
    BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
     SET NOCOUNT ON; 

     BEGIN TRY 
      BEGIN TRAN 

      IF @SmoothieId > 0 
       BEGIN 
        DELETE FROM dbo.SmoothieIngredients 
        WHERE SmoothieId = @SmoothieId; 

        EXECUTE (@Query); 
       END 
      ELSE 
       BEGIN 

        IF @UserId = 0 
         SET @UserId = NULL; 

        INSERT INTO dbo.Smoothie 
          (Name, CreatedDate, Status, UserId) 
        VALUES (N'', @CreatedDate, @Status, @UserId); 

        SET @SmoothieId = SCOPE_IDENTITY(); 

        SET @Query = REPLACE(@Query, 'sId', @SmoothieId); 
        EXECUTE (@Query); 

       END 


      COMMIT TRAN 

      RETURN @SmoothieId 

     END TRY 

     BEGIN CATCH 
      ROLLBACK 
     END CATCH 

    END 

但是,当我使用dapper.net调用此存储过程时,总是返回-1。

 using (var conn = OpenConnection()) 
     { 
      var parameter = new { Query = query, SmoothieId = smoothieId, CreatedDate = createdDate, Status = status, UserId = userId }; 
      return conn.Execute("AddSmoothieIngredients", parameter, commandType: CommandType.StoredProcedure); 
     } 

可能dapper.net无法从存储过程中获取返回值。但我真的不知道如何解决它。请帮忙。

回答

2

它看起来像Dapper.net使用Execute方法的SqlCommand.ExecuteNonQuery。这将返回受影响的行数,而不是返回语句的值。什么你要找的是Query

return connection.Query<int>("AddSmoothieIngredients", parameter, commandType: CommandType.StoredProcedure).First(); 

虽然我不认为这会获取返回语句中,在这种情况下,你需要改变存储过程返回一个结果集。

ALTER PROCEDURE [dbo].[AddSmoothieIngredients] 
    -- Add the parameters for the stored procedure here 
    @Query NVARCHAR(4000) , 
    @SmoothieId INT , 
    @CreatedDate DATETIME , 
    @Status INT , 
    @UserId INT 
AS 
BEGIN 
-- SET NOCOUNT ON added to prevent extra result sets from 
-- interfering with SELECT statements. 
    SET NOCOUNT ON; 

    BEGIN TRY 
     BEGIN TRAN 

     IF @SmoothieId > 0 
      BEGIN 
       DELETE FROM dbo.SmoothieIngredients 
       WHERE SmoothieId = @SmoothieId; 

       EXECUTE (@Query); 
      END 
     ELSE 
      BEGIN 

       IF @UserId = 0 
        SET @UserId = NULL; 

       INSERT INTO dbo.Smoothie 
         (Name, CreatedDate, Status, UserId) 
       VALUES (N'', @CreatedDate, @Status, @UserId); 

       SET @SmoothieId = SCOPE_IDENTITY(); 

       SET @Query = REPLACE(@Query, 'sId', @SmoothieId); 
       EXECUTE (@Query); 

      END 


     COMMIT TRAN 

     SELECT @SmoothieId 
     RETURN 
    END TRY 

    BEGIN CATCH 
     ROLLBACK 
    END CATCH 

END 

或者您可以使用其他数据库访问方法。

+0

感谢。但你仍然需要使用execute,我在网上发现了另一个示例,它可以工作。 – qinking126

13

找到了解决方案,这里是我在网上找到的示例代码。它的工作原理。

var p = new DynamicParameters(); 
p.Add("@a", 11); 
p.Add("@b", dbType: DbType.Int32, direction: ParameterDirection.Output); 
p.Add("@c", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue); 

cnn.Execute("spMagicProc", p, commandType: commandType.StoredProcedure); 

int b = p.Get<int>("@b"); 
int c = p.Get<int>("@c"); 
14

这样执行()返回-1的原因是因为你的存储过程具有SET NOCOUNT ON;根据this question“任何DML消息后‘的’抑制”影响XX行。无论您是否想要禁用该功能,都是该链接中讨论的另一个问题。

我刚刚遇到同样的问题,所以我想我会扔我2美分。

+0

从来不知道这个! +1 – nawfal

1

最近,我不得不改变一个现有的程序,以另外返回一个值,我一直在使用匿名类型来传递参数。在这种情况下,真正好的是DynamicParameters支持匿名类型作为输入参数,这使得这个更改很容易实现。

我有以下几点:

cnn.Execute("spMagicProc", new { a = 11, x = 13, y = 14, z = "something" }, 
    commandType: commandType.StoredProcedure); 

我可以改变,要:

var p = new DynamicParameters(new { a = 11, x = 13, y = 14, z = "something" }); 
p.Add("@rval", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue); 

cnn.Execute("spMagicProc", p, commandType: commandType.StoredProcedure); 

int rval = p.Get<int>("@rval");