1

Web应用程序。C#,SQL 2k8

在一个列表中,在实际的动态 SQL 被执行并返回所需的记录之前,有很多事情正在发生。

最近我们为整个应用程序添加了一些代码(死锁问题),事务提交,回滚和重试 X 次,整个 9 码。

这是一个很大的优势,我们真的需要它。

为了调试列表的任何可能问题,我将动态 SQL 字符串保存在日志表中(它不存储最近几周的旧记录)

问题是:如果列表崩溃,现在没有日志。因为回滚的东西......

到目前为止,我最好的想法是调用列表两次:

  1. "check" - 模式,将创建动态 SQL,将其保存在 LOG tbl 中,但不会执行

  2. "list" - 模式将:

2a. 重新计算动态 SQL

或者

2b。复用“check-mode”创建的动态SQL

无论是 2a 还是 2b,都不应该有很大的性能问题,因为列表存储过程中最昂贵的部分将是动态 sql 的实际执行。“检查” - 模式是一些基本的字符串连接。

死锁重试部分只会进行第二次数据库调用,这也很好!

仍然。我不是有这个想法的最快乐的人。我想知道是否有更好的方法来实现这一点。

4

1 回答 1

1

您可以使用(表)变量和 TRY CATCH 块在事务期间保存数据。变量在回滚后保留。

如果您的翻译在存储​​过程中,则可能如下所示:

BEGIN TRY
    BEGIN TRAN

    DECLARE @SQL NVARCHAR(MAX)
    SET @SQL = 'SELECT 1'

    RAISERROR('A',16,1)

    EXEC (@SQL)

    COMMIT

END TRY
BEGIN CATCH
    ROLLBACK
    SELECT @SQL --WRITE TO LOG TABLE

END CATCH

如果您的事务在 SP 之外 - 在 C# 代码中(这通常是一个更好的主意),您可以使用 RAISERROR 将变量连同发生的实际错误一起发送回应用程序。像这样的东西:

BEGIN TRY

    DECLARE @SQL NVARCHAR(MAX)
    SET @SQL = 'SELECT 1'

    RAISERROR('A',16,1)

    EXEC (@SQL)

END TRY
BEGIN CATCH

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

    SELECT 
        @ErrorMessage = 'Error: ' + ERROR_MESSAGE() + '; SQL: ' + @SQL,
        @ErrorSeverity = ERROR_SEVERITY(),
        @ErrorState = ERROR_STATE()

    RAISERROR (@ErrorMessage,@ErrorSeverity,@ErrorState)

END CATCH
于 2013-04-05T13:31:37.527 回答