I have encountered a bug. Since I have only verified it against the Microsoft SQL Client (SQL Server 2005), I am posting it here, but it is possible that it is not limited to the SQL Client provider.
Scenario: begin a transaction, write to a table, call Complete on the transaction scope, then write again before exiting the transaction block (C# using block). I think that the 2nd write should be rolled back since there is no call to scope.Complete that follows it. But subsequent attempts to read the table that was modified will time out because of a transaction still being held after the transaction scope has been disposed.
Here is a code sample that uses the AggregateDB.AggregateTest table from the (obsolete) NUnit tests:
Code:
1
2 [Test]
3 public void HangingTransactionTest()
4 {
5 // delete entry from previous runs of this test
6 AggregateTestCollection atcs = new AggregateTestCollection();
7
8 // can hang on next line if test was run recently and aborted
9 if (atcs.Query.Where(atcs.Query.LastName == "Faddoul").Load())
10 {
11 atcs.MarkAllAsDeleted();
12 atcs.Save();
13 }
14
15 // start a transaction
16 using (esTransactionScope scope = new esTransactionScope())
17 {
18 AggregateTest aggTest = new AggregateTest();
19 aggTest.AddNew();
20 aggTest.DepartmentID = 1;
21 aggTest.FirstName = "Damuss";
22 aggTest.LastName = "Faddoul";
23 aggTest.Age = 49;
24 aggTest.HireDate = new DateTime(2005, 2, 1);
25 aggTest.Salary = 45.0M;
26 aggTest.IsActive = true;
27
28 aggTest.Save();
29
30 scope.Complete();
31
32 // now write again (after the xact Complete!!)
33
34 aggTest.Salary = 44.5M;
35 aggTest.Save();
36
37 // do not end with a Complete. should roll back, right?
38 }
39
40 atcs = new AggregateTestCollection();
41
42 // try to read, but attempt will hang.
43 Assert.AreEqual(true, atcs.Query.Where(atcs.Query.LastName == "Faddoul").Load());
44
45 Assert.AreEqual(1, atcs.Count); // never get here
46
47 foreach (AggregateTest faddoul in atcs)
48 {
49 Assert.AreEqual(45.0M, faddoul.Salary);
50 }
51 }
52
Of course, you could argue that no db modifications are allowed after the call to scope.Complete(). Bear in mind that this is an extremely simplified sample case that demonstrates the bug. The actual code that evoked the bug had several nested levels of subroutines and try/catch blocks to contend with. The "2nd write" was actually done inside an exception handling block which attempted to record a processing error in the database.
- -
randall.