【问题标题】:Dapper return print message from stored procedureDapper 从存储过程返回打印消息
【发布时间】:2020-05-01 10:04:23
【问题描述】:

我有一个无法修改的存储过程,我正在尝试获取 PRINT 消息,如果发生错误,该消息将返回。我的存储过程中的代码是。

IF((ISNULL(@ID,''))='')
BEGIN
    PRINT N'Error: This ID is invalid.'; 
    RETURN;
END

在我的简洁通话中,我有以下内容:

var storedProcResult = connection.Query("AdventureWorks.dbo.myStoredProcedure", new
{
    @ID = null
},
 commandType: CommandType.StoredProcedure
);

storedProcResult 的值是 0,但我有兴趣收到 PRINT 消息。请指教。

【问题讨论】:

  • 我认为 Dapper 对此没有任何特别之处。您可以手动将处理程序连接到SqlConnection.InfoMessage - 但是,对于错误代码,您真正想要的是THROW / RAISERROR,因此您会得到一个实际的SqlExceptionPRINT 消息很容易被客户端忽略,事实上绝大多数确实忽略它们。编写此程序的人是否生活在只使用 Management Studio 进行所有工作且没有人忽略“消息”选项卡的地方?从长远来看,这似乎是不可行的。
  • 我大约 99%(左右)确信您不走运。你的 sproc 什么都不返回。 PRINT 语句只是写入控制台
  • 如果我能够修改存储过程,那么获取错误消息的最佳方法是什么。使用错误代码?
  • @Flydog57 没有控制台;它写入 TDS 流;您可以通过InfoMessage 接收该信息(SSMS 等只是在内部执行完全相同的操作,并将其呈现为好像有 控制台)
  • 确认:@JeroenMostert 是正确的 - Dapper 目前绝对没有为此做出任何规定,原因有多种,但并非最不重要的是:此 API (InfoMessage) 位于 connection 级别,而不是 command,Dapper 最感兴趣的是将命令作为工作单元。另外:它不是在DbConnection 上定义的,而是SqlConnection 特定的(Dapper 尽量与连接无关)。但是:只需在您的代码中订阅InfoMessage,您就应该设置好了!

标签: c# sql sql-server tsql dapper


【解决方案1】:

您可以使用下面的结构,只需替换 @ErrorMessage 变量的值。

CREATE OR ALTER PROCEDURE DBO.SPR_PROCEDURE_NAME()AS
BEGIN

    DECLARE 
     @ErrorMessage NVARCHAR(4000)
    ,@ErrorSeverity INT
    ,@ErrorState INT

    BEGIN TRY



        --YOUR CODE HERE



    END TRY

    BEGIN CATCH     
        IF (XACT_STATE()) = -1
            ROLLBACK TRAN

        SELECT @ErrorMessage = ERROR_MESSAGE(),
               @ErrorSeverity = ERROR_SEVERITY(),  
               @ErrorState = ERROR_STATE();  
        RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);

    END CATCH

END

【讨论】:

    【解决方案2】:

    基于 Jeroen 和 Marc 的 cmets,我编写了一个非常基本的代码来获取单个命令的消息:

    var infoMessageBuilder = new StringBuilder();
    
    void OnInfoMessageEvent(object _, SqlInfoMessageEventArgs args)
    {
        infoMessageBuilder.AppendLine(args.Message);
    }
    
    // Register message event listener
    cn.InfoMessage += OnInfoMessageEvent;
    await cn.ExecuteAsync("AdventureWorks.dbo.myStoredProcedure", new {@ID = null}, commandType: CommandType.StoredProcedure);
    
    // Unregister listener to stop fetching events from the connection
    cn.InfoMessage -= OnInfoMessageEvent;
    
    // Get messages as string
    var message = infoMessageBuilder.ToString();
    

    我在命令执行之前注册了一个事件处理程序,并将 InfoMessage 事件的所有输出写入 StringBuilder。处理程序将在执行后被删除。这对我来说非常好。希望它可以帮助到这里的其他人。

    【讨论】:

      猜你喜欢
      • 2014-10-15
      • 1970-01-01
      • 2016-01-21
      • 1970-01-01
      • 2020-07-14
      • 2017-07-21
      • 1970-01-01
      • 2021-08-15
      • 1970-01-01
      相关资源
      最近更新 更多