SQL Server 和 TransactionScope(带有 MSDTC):偶尔无法获取连接

发布于 2024-09-06 01:59:48 字数 1791 浏览 2 评论 0原文

我已经为 .net 代码编写了一些测试,这些测试调用了对我的 SQL Server 的调用。看来使用 System.Transactions 是回滚对数据库产生的任何修改的绝佳选择。我知道一些纯粹主义者会建议我可能想模拟数据库,但我不会走那条路;这不是严格意义上的纯粹的单元测试。

当我编写并运行多个测试时,这完全按照预期工作。我只是将用于初始化和中止 .net 事务的代码放入测试设置和测试拆卸方法中。这似乎是一个很好的解决方案。

然而,我遇到的问题是,当我尝试运行 100 个这样的测试时,其中许多测试都会抛出无法连接到 SQL Server 的异常,即使它们在逐一运行时通过了。更糟糕的是,当我运行测试时,数据库中的表有时会被锁定。我必须请我的 DBA 手动删除锁。

正如许多人所知,在针对 SQL 服务器的开发工作站上运行的代码(如运行此测试)上使用 TransactionScope 将使 .net 框架使用 MSDTC。

这是一个代码示例来说明我正在做的事情:

  <测试初始化​​()>公共子 MyTestInitialize()
    _scope = 新 System.Transactions.TransactionScope( _
        System.Transactions.TransactionScopeOption.Required,新的 TimeSpan(0, 2, 0))
结束子
<TestCleanup()> Public Sub MyTestCleanup()
    _scope.Dispose()
End Sub

<TestMethod()> Public Sub CurrentProgramUser_Get_UserID()
    Dim ProgramSessionId As String
    Dim CurrentProgramUserId As Integer
    Dim dSession As ProgramSession
    CurrentDCMAUserId = Convert.ToInt32( _
    SqlHelper.ExecuteScalar(testDcmaConnString, System.Data.CommandType.Text, _
    "INSERT into Program_Users(UserName,FirstName,LastName) " & _
    "VALUES('GuitarPlayer','Bob','Marley')" & _
    "SELECT IDENT_CURRENT('Program_users') ") _
                         )
    ProgramSessionId = session.getCurrentSession()
    session.WriteUserParam("Program", ProgramSessionId, "USERID", CurrentProgramUserId.ToString(), testSource, testConnString)

    Dim readValue As Integer
    readValue = session.User.UserID

    Assert.AreEqual(CurrentProgramUserId, readValue)
End Sub

正如您所看到的,这里没有什么特别奇特的地方。我只有一个测试方法,它将向我的数据库写入一些我希望我的方法找到的内容。这只是一个例子;还有许多其他类似的测试。

我的测试逻辑似乎是合理的。是什么可能导致我的测试不仅失败,而且偶尔将用户锁定在表之外?

I've written some tests for .net code that invokes calls to my SQL Server. It appears that using System.Transactions is an excellent choice for rolling back any modifications to the database that result. I'm aware that some purists would suggest that I might want to mock the database, but I'm not going down that road; this is not strictly pure unit-testing.

When I write and run several tests, this works exactly as expected. I simply put the code to initialize and abort .net transactions in the test setup and test teardown methods. It seemed like a great solution.

However, the problem I have is that when I try to run 100 of these tests, many of them will throw exception that they could not connect to the SQL Server even though they pass when run one-by-one. To make matters even worse, the tables in my database sporadically get locked sometimes when I run my tests. I have to ask my DBA to manually remove the locks.

As many of you will know, using TransactionScope on code that runs on a development workstation (as in running this test) against a SQL server will make the .net framework use MSDTC.

Here's a code sample to illustrate what I'm doing:

 <TestInitialize()> Public Sub MyTestInitialize()
    _scope = New System.Transactions.TransactionScope( _
        System.Transactions.TransactionScopeOption.Required, New TimeSpan(0, 2, 0))
End Sub
<TestCleanup()> Public Sub MyTestCleanup()
    _scope.Dispose()
End Sub

<TestMethod()> Public Sub CurrentProgramUser_Get_UserID()
    Dim ProgramSessionId As String
    Dim CurrentProgramUserId As Integer
    Dim dSession As ProgramSession
    CurrentDCMAUserId = Convert.ToInt32( _
    SqlHelper.ExecuteScalar(testDcmaConnString, System.Data.CommandType.Text, _
    "INSERT into Program_Users(UserName,FirstName,LastName) " & _
    "VALUES('GuitarPlayer','Bob','Marley')" & _
    "SELECT IDENT_CURRENT('Program_users') ") _
                         )
    ProgramSessionId = session.getCurrentSession()
    session.WriteUserParam("Program", ProgramSessionId, "USERID", CurrentProgramUserId.ToString(), testSource, testConnString)

    Dim readValue As Integer
    readValue = session.User.UserID

    Assert.AreEqual(CurrentProgramUserId, readValue)
End Sub

As you can see, there's nothing particularly fancy here. I just have a test method that's going to write some stuff to my database that I want my method to find. This is only one example; there are many other tests like it.

The logic of my tests appears to be sound. What could be causing my tests to not only fail, but sporadically lock users out of tables?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

岁月蹉跎了容颜 2024-09-13 01:59:48

我发现了问题。我测试的方法之一使用 SqlDataReader 对象。显然,必须在 SqlDataReader 超出范围之前调用 Close() 方法才能释放连接,但就我而言,我未能这样做。

只需将 mySqlDataReader.Close() 添加到被测方法的末尾即可解决问题。此外,测试此特定方法的测试方法是数据驱动的,具有 100 多个测试用例,因此这解释了我如何耗尽连接。

I found the problem. One of the methods I was testing uses a SqlDataReader object. Apparently, the Close() method must be called before the SqlDataReader goes out of scope in order to release the connection, but in my case, I failed to do so.

Simply adding mySqlDataReader.Close() to the end of the method under test fixed the problem. Also, the test method to test this particular method was data-driven with over 100 test cases, so that explains how I could have run out of connections.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文