0

I get some data from a source and I want to add them in the database, so I open a context for each batch and use a transaction to commit the changes after all the data was added.

My code:

      using (var conn = new SqlConnection(dataAccessSettings.DatabaseConnectString))
      {
        conn.Open();

        using (var sqlTxn = conn.BeginTransaction(System.Data.IsolationLevel.Snapshot))
        {
          foreach (var dataBatch in GetData())
          {
            using (var context = new DataContext(conn, false))
            {
              context.Database.UseTransaction(sqlTxn);
              context.DataTable.AddRange(dataBatch);

              context.SaveChanges();
            }
          }
          sqlTxn.Commit();
        }
      }

However, when the second context calls the context.Database.UseTransaction(sqlTxn) I get the following error:

The transaction passed in must have a non-null connection. A null connection indicates the transaction has already been completed.

I set the contextOwnsConnection constructor parameter of the context to false so what exactly is closing my connection?

Mark Uivari
  • 245
  • 2
  • 5
  • 16

2 Answers2

0

You must remove SaveChanged in loop statement.

If you call it inside the loop, EF will write back the changes to the database for every single entity (and every entity will be in its own, separate transaction), One call with 50 changes is typically much better / faster / more efficient than 50 calls for 1 change each.

Change Code for it

      using (var conn = new SqlConnection(dataAccessSettings.DatabaseConnectString))
  {
    conn.Open();

    using (var sqlTxn = conn.BeginTransaction(System.Data.IsolationLevel.Snapshot))
    {
      foreach (var dataBatch in GetData())
      {
        using (var context = new DataContext(conn, false))
        {
          context.Database.UseTransaction(sqlTxn);
          context.DataTable.AddRange(dataBatch);
          // remove SaveChanges here
        }
      }
      sqlTxn.Commit();
      context.SaveChanges();
    }
  }
Zanyar Jalal
  • 1,407
  • 12
  • 29
0

based off : Using Transactions or SaveChanges(false) and AcceptAllChanges()?

using (var conn = new SqlConnection(dataAccessSettings.DatabaseConnectString))
using (var context = new BloggingContext(conn, false)) 
{ 
    using (var dbContextTransaction = context.Database.BeginTransaction()) 
    { 
        try 
        { 
            foreach (var dataBatch in GetData())
            {
                context.Database.UseTransaction(sqlTxn);
                context.DataTable.AddRange(dataBatch);
            }

            context.SaveChanges(); 

            dbContextTransaction.Commit(); 
        } 
        catch (Exception) 
        { 
            dbContextTransaction.Rollback(); //Required according to MSDN article 
            throw; //Not in MSDN article, but recommended so the exception still bubbles up
        } 
    } 
} 
}
Seabizkit
  • 2,417
  • 2
  • 15
  • 32