Index: System.Data.SQLite/SQLiteConnection.cs ================================================================== --- System.Data.SQLite/SQLiteConnection.cs +++ System.Data.SQLite/SQLiteConnection.cs @@ -725,18 +725,20 @@ /// Manual distributed transaction enlistment support /// /// The distributed transaction to enlist in public override void EnlistTransaction(System.Transactions.Transaction transaction) { - if (_transactionLevel > 0 && transaction != null) - throw new ArgumentException("Unable to enlist in transaction, a local transaction already exists"); - if (_enlistment != null && transaction == _enlistment._scope) return; else if (_enlistment != null) throw new ArgumentException("Already enlisted in a transaction"); + if (_transactionLevel > 0 && transaction != null) + throw new ArgumentException("Unable to enlist in transaction, a local transaction already exists"); + else if (transaction == null) + throw new ArgumentNullException("Unable to enlist in transaction, it is null"); + _enlistment = new SQLiteEnlistment(this, transaction); } #endif /// ADDED Tests/tkt-ccfa69fc32.eagle Index: Tests/tkt-ccfa69fc32.eagle ================================================================== --- /dev/null +++ Tests/tkt-ccfa69fc32.eagle @@ -0,0 +1,83 @@ +############################################################################### +# +# tkt-ccfa69fc32.eagle -- +# +# Written by Joe Mistachkin. +# Released to the public domain, use at your own risk! +# +############################################################################### + +package require Eagle +package require EagleLibrary +package require EagleTest + +runTestPrologue + +############################################################################### + +source [file join $path common.eagle] +runSQLiteTestPrologue + +############################################################################### + +# +# NOTE: Setup the variables that refer to the various files required by the +# tests in this file. +# +set testLinqExeFile [getBuildFileName testlinq.exe] +set northwindEfDbFile [file nativename [file join [file dirname $path] \ + testlinq northwindEF.db]] + +# +# NOTE: Setup the test constraints specific to the tests in this file. +# +if {![haveConstraint file_[file tail $testLinqExeFile]]} then { + checkForFile $test_channel $testLinqExeFile +} + +if {![haveConstraint file_[file tail $northwindEfDbFile]]} then { + checkForFile $test_channel $northwindEfDbFile +} + +############################################################################### + +runTest {test tkt-ccfa69fc32-1.1 {Entity Framework / Transaction Scope} -body { + set result [list] + + foreach add [list false true false] { + set code [catch { + testExec $testLinqExeFile [list -eventflags Wait -directory \ + [file dirname $testLinqExeFile] -nocarriagereturns -stdout output \ + -success 0] -efTransaction $add + } error] + + tlog "---- BEGIN STDOUT OUTPUT\n" + tlog $output + tlog "\n---- END STDOUT OUTPUT\n" + + lappend result $code + + if {$code == 0} then { + lappend result [string trim $output] + } else { + lappend result [string trim $error] + } + } + + set result +} -cleanup { + unset -nocomplain code output error result add +} -constraints {eagle file_testlinq.exe file_northwindEF.db} -match glob \ +-result {0 {1581 1730 1833 2116 2139} 0 {System.Data.UpdateException: * --->\ +System.Data.SQLite.SQLiteException: Abort due to constraint violation +PRIMARY KEY must be unique +*} 0 {1 2 3 4 5 6 7 8 9 10 1576 1577 1578 1579 1580 1581 1730 1833 2116 2139}}} + +############################################################################### + +unset -nocomplain testLinqExeFile northwindEfDbFile + +############################################################################### + +runSQLiteTestEpilogue +runTestEpilogue Index: testlinq/Program.cs ================================================================== --- testlinq/Program.cs +++ testlinq/Program.cs @@ -1,10 +1,11 @@ using System; using System.Diagnostics; using System.Linq; using System.Data.Objects; using System.Text; +using System.Transactions; namespace testlinq { class Program { @@ -85,10 +86,28 @@ value = value.Trim(); } return StartsWithTest(value); } + case "eftransaction": + { + bool value = false; + + if (args.Length > 1) + { + if (!bool.TryParse(args[1], out value)) + { + Console.WriteLine( + "cannot parse \"{0}\" as boolean", + args[1]); + + return 1; + } + } + + return EFTransactionTest(value); + } default: { Console.WriteLine("unknown test \"{0}\"", arg); return 1; } @@ -176,10 +195,100 @@ Console.Write(customers.CustomerID); once = true; } } + + return 0; + } + + // + // NOTE: Used to test the fix for ticket [ccfa69fc32]. + // + private static int EFTransactionTest(bool add) + { + // + // NOTE: Some of these territories already exist and should cause + // an exception to be thrown when we try to INSERT them. + // + long[] territoryIds = new long[] { + 1, 2, 3, 4, 5, // NOTE: Success + 6, 7, 8, 9, 10, // NOTE: Success + 1576, 1577, 1578, 1579, 1580, // NOTE: Success + 1581, 1730, 1833, 2116, 2139, // NOTE: Fail (1581) + 2140, 2141 // NOTE: Skipped + }; + + if (add) + { + using (northwindEFEntities db = new northwindEFEntities()) + { + using (TransactionScope scope = new TransactionScope()) + { + // + // NOTE: *REQUIRED* This is required so that the + // Entity Framework is prevented from opening + // multiple connections to the underlying SQLite + // database (i.e. which would result in multiple + // IMMEDIATE transactions, thereby failing [later + // on] with locking errors). + // + db.Connection.Open(); + + foreach (int id in territoryIds) + { + Territories territories = new Territories(); + + territories.TerritoryID = id; + territories.TerritoryDescription = String.Format( + "Test Territory #{0}", id); + territories.Regions = db.Regions.First(); + + db.AddObject("Territories", territories); + } + + try + { +#if NET_20 + db.SaveChanges(false); +#else + db.SaveChanges(SaveOptions.None); +#endif + } + catch (Exception e) + { + Console.WriteLine(e); + } + finally + { + scope.Complete(); + db.AcceptAllChanges(); + } + } + } + } + else + { + using (northwindEFEntities db = new northwindEFEntities()) + { + bool once = false; + var query = from t in db.Territories + where territoryIds.AsQueryable().Contains(t.TerritoryID) + orderby t.TerritoryID + select t; + + foreach (Territories territories in query) + { + if (once) + Console.Write(' '); + + Console.Write(territories.TerritoryID); + + once = true; + } + } + } return 0; } private static int OldTests() Index: testlinq/testlinq.2008.csproj ================================================================== --- testlinq/testlinq.2008.csproj +++ testlinq/testlinq.2008.csproj @@ -44,10 +44,11 @@ + @@ -69,14 +70,15 @@ + Index: testlinq/testlinq.2010.csproj ================================================================== --- testlinq/testlinq.2010.csproj +++ testlinq/testlinq.2010.csproj @@ -41,10 +41,11 @@ + +