title: Exceptions when rolling back a transaction - connection already closed?
body: <p>Using Entity Framework 6.0.0, I'm seeing an exception when closing a transaction.</p>
  
  <p>We'd been having problems with concurrent changes to the table, so I wrapped it in a transaction, and now I'm getting exceptions on rollback.</p>
  
  <p>The code:</p>
  
  <pre><code>public LockInfo getSharedLock(string jobid)
  {
      using (var myDbContext = new MyDbContext())
      {
          using (var transaction = myDbContext.Database.BeginTransaction())
          {
              try
              {
                  this.logger.log("Attempting to get shared lock for {0}", jobid);
  
                  var mylocks =
                      myDbContext.joblocks.Where(j =&gt; j.customerid == this.userContext.customerid)
                          .Where(j =&gt; j.jobid == jobid)
                          .Where(j =&gt; j.operatorid == this.userContext.operatorid);
  
                  var exclusiveLock = mylocks.FirstOrDefault(
                      j =&gt; j.lockstatus == LockInfo.LockState.Exclusive);
                  if (exclusiveLock != null)
                  {
                      this.logger.log("{0} already had exclusive lock, ignoring", jobid);
                      return LockInfo.populate(exclusiveLock);
                  }
  
                  var sharedLock = mylocks.FirstOrDefault(
                      j =&gt; j.lockstatus == LockInfo.LockState.Shared);
                  if (sharedLock != null)
                  {
                      this.logger.log("{0} already had shared lock, ignoring", jobid));
                      sharedLock.lockdt = DateTime.Now;
                      myDbContext.SaveChanges();
  
                      return LockInfo.populate(sharedLock);
                  }
  
                  var joblock = new joblock
                  {
                      customerid = this.userContext.customerid,
                      operatorid = this.userContext.operatorid,
                      jobid = jobid,
                      lockstatus = LockInfo.LockState.Shared,
                      sharedLock.lockdt = DateTime.Now
                  };
  
                  myDbContext.joblocks.Add(joblock);
                  myDbContext.SaveChanges();
                  transaction.Commit();
  
                  this.logger.log("Obtained shared lock for {0}", jobid);
                  return LockInfo.populate(joblock);
              }
              catch (Exception ex)
              {
                  transaction.Rollback();
                  this.logger.logException(ex, "Exception in getSharedLock(\"{0}\")", jobid);
                  throw;
              }
          }
      }
  }
  </code></pre>
  
  <p>You can see the logging, in the code above. We have logging enabled in the database, too.  The log trace:</p>
  
  <pre><code>===================
  NORMAL    TicketLockController.getLock("AK2015818002WL")
  ===================
  SQL    Opened connection at 9/22/2015 2:47:49 PM -05:00
  ===================
  SQL    Started transaction at 9/22/2015 2:47:49 PM -05:00
  ===================
  NORMAL    Attempting to get shared lock for AK2015818002WL
  ===================
  SQL    SELECT TOP (1) [Extent1].[customerid] AS [customerid]
      ,[Extent1].[jobid] AS [jobid]
      ,[Extent1].[lockdtdate] AS [lockdtdate]
      ,[Extent1].[lockdttime] AS [lockdttime]
      ,[Extent1].[operatorid] AS [operatorid]
      ,[Extent1].[lockstatus] AS [lockstatus]
      ,[Extent1].[changes] AS [changes]
  FROM [dbo].[joblock] AS [Extent1]
  WHERE ([Extent1].[customerid] = 'TESTTK')
      AND ([Extent1].[jobid] = 'AK2015818002WL')
      AND ([Extent1].[operatorid] = 'ADMIN')
      AND (N'Exclusive' = [Extent1].[lockstatus])
  ===================
  SQL    SELECT TOP (1) [Extent1].[customerid] AS [customerid]
      ,[Extent1].[jobid] AS [jobid]
      ,[Extent1].[lockdtdate] AS [lockdtdate]
      ,[Extent1].[lockdttime] AS [lockdttime]
      ,[Extent1].[operatorid] AS [operatorid]
      ,[Extent1].[lockstatus] AS [lockstatus]
      ,[Extent1].[changes] AS [changes]
  FROM [dbo].[joblock] AS [Extent1]
  WHERE ([Extent1].[customerid] = 'TESTTK')
      AND ([Extent1].[jobid] = 'AK2015818002WL')
      AND ([Extent1].[operatorid] = 'ADMIN')
      AND (N'Shared' = [Extent1].[lockstatus])
  ===================
  SQL    INSERT [dbo].[joblock] (
      [customerid]
      ,[jobid]
      ,[lockdtdate]
      ,[lockdttime]
      ,[operatorid]
      ,[lockstatus]
      ,[changes]
      )
  VALUES (
      @0
      ,@1
      ,@2
      ,@3
      ,@4
      ,@5
      ,NULL
      )
  ===================
  SQL    Closed connection at 9/22/2015 2:47:50 PM -05:00
  ===================
  EXCEPTION    Unhandled exception caught: The underlying provider failed on Rollback.
  ===================
  EXCEPTION    Inner Exception: Value cannot be null.
  Parameter name: connection
  </code></pre>
  
  <p>The two selects are succeeding, then the insert is failing for some reason. throwing an exception, and for some reason the connection is closing before the Rollback() executes.</p>
  
  <p>Any ideas what I'm doing wrong?</p>
  
  <p>==== Adding stack traces ====</p>
  
  <p>Stacktrace for the outer exception:</p>
  
  <pre><code>   at System.Data.Entity.Core.EntityClient.EntityTransaction.Rollback()
     at korterra.kt_api.Shared.TicketLockWrangler.getSharedLock(String jobid)
     at korterra.kt_ws.ApiControllers.Shared.TicketLockController.getSharedLock(TicketLockDTO ticketLockDTO)
     at lambda_method(Closure , Object , Object[] )
     at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.&lt;&gt;c__DisplayClass10.&lt;GetExecutor&gt;b__9(Object instance, Object[] methodParameters)
     at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)
     at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)
  --- End of stack trace from previous location where exception was thrown ---
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     at System.Web.Http.Tracing.ITraceWriterExtensions.&lt;TraceBeginEndAsyncCore&gt;d__18`1.MoveNext()
  --- End of stack trace from previous location where exception was thrown ---
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     at System.Web.Http.Controllers.ApiControllerActionInvoker.&lt;InvokeActionAsyncCore&gt;d__0.MoveNext()
  --- End of stack trace from previous location where exception was thrown ---
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     at System.Web.Http.Tracing.ITraceWriterExtensions.&lt;TraceBeginEndAsyncCore&gt;d__18`1.MoveNext()
  --- End of stack trace from previous location where exception was thrown ---
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     at System.Web.Http.Controllers.ActionFilterResult.&lt;ExecuteAsync&gt;d__2.MoveNext()
  --- End of stack trace from previous location where exception was thrown ---
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     at System.Web.Http.Filters.AuthorizationFilterAttribute.&lt;ExecuteAuthorizationFilterAsyncCore&gt;d__2.MoveNext()
  --- End of stack trace from previous location where exception was thrown ---
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
     at System.Web.Http.Controllers.ExceptionFilterResult.&lt;ExecuteAsync&gt;d__0.MoveNext()
  </code></pre>
  
  <p>Stacktrace for the inner exception:</p>
  
  <pre><code>   at System.Data.Entity.Utilities.Check.NotNull[T](T value, String parameterName)
     at System.Data.Entity.Infrastructure.Interception.DbTransactionInterceptionContext.WithConnection(DbConnection connection)
     at System.Data.Entity.Infrastructure.Interception.DbTransactionDispatcher.Rollback(DbTransaction transaction, DbInterceptionContext interceptionContext)
     at System.Data.Entity.Core.EntityClient.EntityTransaction.Rollback()
  </code></pre>