The EntitySpaces Community

Share and learn about the EntitySpaces Architecture.
Welcome to The EntitySpaces Community Sign in | Join | Help
in
Home Forums Photos

Question about esTransactionScope ...

Last post 10-09-2007, 1:01 PM by Mike.Griffin. 7 replies.
Sort Posts: Previous Next
  •  10-08-2007, 2:27 PM 5695

    Question about esTransactionScope ...

    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.
  •  10-08-2007, 2:58 PM 5696 in reply to 5695

    Re: esTransactionScope leaves hanging transaction after Dispose

    I suppose that I should have mentioned that this is the EntitySpaces 2007.0.0913.0 beta.

    Windows XP SP2 

    MyGeneration  1.2.0.7

     


    - -
    randall.
  •  10-08-2007, 4:23 PM 5697 in reply to 5696

    Re: esTransactionScope leaves hanging transaction after Dispose

    I just tested this code:

     

    Code:
    using (esTransactionScope scope = new esTransactionScope())
    {
        Employee emp1 = new Employee();
        emp1.LastName = "goo9";
        emp1.FirstName = "goo9";
        emp1.Save();
    
        using (esTransactionScope scopeNested = new esTransactionScope())
        {
            Employee emp2 = new Employee();
            emp2.LastName = "goo10";
            emp2.FirstName = "goo10";
            emp2.Save();
    
            //scope.Complete();
        }
    
        scope.Complete();
    }
     

    It works perfectly, no data makes it to the database. Notice I commented out the nested transactions scope.Complete() call, once a transaction at any level fails to call scope.Complete() the entire transaction tree is doomed. Of course, writing to your database after scope.Complete() is just unsupported, it should always be the last line of code in a using esTransaction block. I suppose we could try and detect that condition, I'll take a look at it. Meanwhile, if you can use Northwind and create a tiny Windows.Forms app that demonstrates a bug we'll look at it.

     


    EntitySpaces | Twitter | BLOG | Please honor our Software License
  •  10-08-2007, 4:26 PM 5698 in reply to 5697

    Re: esTransactionScope leaves hanging transaction after Dispose

    FYI. We changed the title of this thread (which isn't unusual) so don't take it personal. We get posts all the time that this doesn't work and that doesn't work and it turns out it does.
  •  10-09-2007, 9:42 AM 5720 in reply to 5697

    Re: esTransactionScope leaves hanging transaction after Dispose

    Apparently, I failed to make my objection clear.

    It doesn't matter to me whether the operations inside the esTransactionScope make it into the database or not in the code I posted.

    The real problem is that other operations are blocked after the esTransactionScope is disposed.  In fact, other processes reading the same table are also blocked.  It remains in this state until the errant process exits and the database server retires the connection.

    I'll try to create a Northwind Forms app that demonstrates the problem.  How do I send the zip to you?


    - -
    randall.
  •  10-09-2007, 10:04 AM 5721 in reply to 5720

    Re: esTransactionScope leaves hanging transaction after Dispose

    Okay, let me check this out, however, you agree that this is do to a programming error right? I mean, it's only due to writing to the table after calling scope.Complete(). I will see if tonight I can put in some detection code for that case. I'll test Microsofts TransactionScope and trying updating after a call to scope.Complete() too and see what they do. If you want to send a sample send it to support@entityspaces.net in a zip file, thanx.

    EntitySpaces | Twitter | BLOG | Please honor our Software License
  •  10-09-2007, 12:31 PM 5725 in reply to 5721

    Re: esTransactionScope leaves hanging transaction after Dispose

    I've sent a sample zip to support@entityspaces.net. 

    Yes, I agree that db mods after the call to Complete are a no-no.  Some bonehead that I work with reverse-nested the try/catch with the using block:

     

    Code:
    using (esTransactionScope scope = new esTransactionScope())
    {
        try
        {
            blah, blah
            scope.Complete()
            
            other code that doesn't write db, but might throw exception
        }
        catch (...)
        {
             code that records exception in db  (whoops!)
        }
    }

    I sifted thru the code and tried to fix all the occurences, but I can't be absolutely sure that I found them all.  It would be really nice if ES would Dispose the SqlTransaction when the outermost esTransactionScope is disposed.

    Thanks! 


    - -
    randall.
  •  10-09-2007, 1:01 PM 5727 in reply to 5725

    Re: esTransactionScope leaves hanging transaction after Dispose

    Excellent, thanx, I'm sure we can detect that ....

    EntitySpaces | Twitter | BLOG | Please honor our Software License
View as RSS news feed in XML