Web应用程序。 C#,SQL 2k8
在列表中,在执行实际的动态SQL之前会发生很多事情,并返回所需的记录。
最近我们为整个应用程序(死锁问题)添加了一些代码,包括事务提交,回滚和重试X次,整个9码。
这是一个很大的优点,我们真的需要它。
BUT
为了调试列表的任何可能的问题,我将动态SQL字符串保存在日志表中(仅在过去几周内不存储旧记录)
问题是:如果列表崩溃,现在没有日志。因为回滚的东西......
到目前为止,我最好的想法是将列表调用两次:
“check” - 模式,将创建动态SQL,将其保存在LOG tbl中,但不会执行
“list” - 模式将:
2a上。重新计算动态SQL
或
2B。重用“check - mode
创建的动态SQL2a或2b,不应该有巨大的性能问题,因为列表存储过程中最昂贵的部分是动态sql的实际执行。 “检查” - 模式是一些基本的字符串连接。
死锁重试部分只会执行第二次db调用,这也很好!
静止。 我不是这个想法中最开心的人。 我想知道是否有更好的方法来实现这一目标。
答案 0 :(得分: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