与如何在RollBack上捕获异常相关但不相同
如果我们捕获并显式回滚,我们似乎需要尝试/捕获包装回滚调用。彻底消除try/catch是否仍然是回滚,如果回滚失败,仍然会发送根原因异常而不是回滚异常吗?我已经尝试过如何复制这个,但是我不知道如何强制回滚超时。
这是遗留模式:
using (SqlConnection conn = new SqlConnection(ConnectionString))
{
conn.Open();
using (SqlTransaction trans = conn.BeginTransaction())
{
try
{
//do stuff
trans.Commit();
}
catch
{
trans.Rollback();
throw;
}
}
}发布于 2014-10-24 16:39:34
这是我在整个职业生涯中使用和看到的一种模式。最近,我遇到了一种情况,在生产中出现异常,堆栈跟踪显示回滚超时,而不是实际发生的异常。从我的分析中可以看出,更好的做法是不要在捕获中使用显式Rollback,而是让using语句来处理它。
这允许正确的根原因异常冒泡,事务将在服务器上回滚。为了复制Rollback超时,我创建了一个表和一个过程,并从单元测试中调用事务中的存储过程。
/****** Object: Table [dbo].[Table_1] Script Date: 10/24/2014 12:07:42 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Table_1](
[id] [int] NULL,
[GuidTest] [uniqueidentifier] NULL,
[GuidTest2] [uniqueidentifier] NULL,
[GuidTest3] [uniqueidentifier] NULL
) ON [PRIMARY]
/****** Object: StoredProcedure [dbo].[Test_RollBack] Script Date: 10/24/2014 12:08:04 PM ******/
/****** Object: StoredProcedure [dbo].[Test_RollBack] Script Date: 10/24/2014 12:08:04 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[Test_RollBack]
AS
BEGIN
DECLARE @counter int = 1
while @counter < 3000000
BEGIN
INSERT INTO Table_1(id, GuidTest, GuidTest2, GuidTest3)
VALUES(@counter, newId(), newId(), newId())
set @counter = @counter + 1
END
update Table_1
SET GuidTest = newid()
END
GO
[TestMethod()]
public void RollBackTestTimeout()
{
using (SqlConnection conn = new SqlConnection("Your ConnectionString"))
{
conn.Open();
using (SqlTransaction trans = conn.BeginTransaction())
{
using (SqlCommand cmd = new SqlCommand())
{
try
{
cmd.Connection = conn;
cmd.Transaction = trans;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "Test_RollBack";
cmd.ExecuteNonQuery();
trans.Commit();
}
catch
{
trans.Rollback();
throw;
}
}
}
}
}
[TestMethod()]
public void RollBackTestTimeout_WithUsing()
{
using (SqlConnection conn = new SqlConnection("Your ConnectionString"))
{
conn.Open();
using (SqlTransaction trans = conn.BeginTransaction())
{
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.Transaction = trans;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "Test_RollBack";
cmd.ExecuteNonQuery();
trans.Commit();
}
}
}
}对我来说,RollBackTestTimeout测试方法抛出一个SqlCommandTimeout,但是报告回滚超时,RollBackTestTimeout_WithUsing实际上显示了根本原因异常。因此,根据我所发现的,我会说,让使用句柄,以便您可以调试您的问题在生产以后。
https://stackoverflow.com/questions/26552079
复制相似问题