1

We have an application that handles XML files. The application uses an EF 6 to save data to the DB. The application handles the files in concurrent threads using ThreadPool.QueueUserWorkItem method. The application has worked fine for 1,5 year. Now we started to get EF exception as following:

Most of the times there are no such error, but it is raised a few times a day. We doest succeeded to figure out what are the reasons or conditions that cause an EF to raise this error.

Any suggestions?

 An error occurred while starting a transaction on the provider connection. See the inner exception for details.
   at System.Data.Entity.Core.EntityClient.EntityConnection.BeginDbTransaction(IsolationLevel isolationLevel)
   at System.Data.Entity.Core.EntityClient.EntityConnection.BeginTransaction()
   at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
   at System.Data.Entity.Core.Objects.ObjectContext.SaveChangesToStore(SaveOptions options, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction)
   at System.Data.Entity.Infrastructure.DbExecutionStrategy.Execute[TResult](Func`1 operation)
   at System.Data.Entity.Core.Objects.ObjectContext.SaveChangesInternal(SaveOptions options, Boolean executeInExistingTransaction)
   at System.Data.Entity.Internal.InternalContext.SaveChanges()
   at Albatross.Core.Utilities.BasicDataRepository`2.Update(T entity) in c:\DevTFS\AlbatrossEmployers\AlbatrossEmployers_DevTiyuvHeshb\Albatross.Core\Utilities\BasicDataRepository.cs:line 177
****** Inner Exception - START ******
SqlConnection does not support parallel transactions.
   at System.Data.SqlClient.SqlInternalConnection.BeginSqlTransaction(IsolationLevel iso, String transactionName, Boolean shouldReconnect)
   at System.Data.SqlClient.SqlConnection.BeginTransaction(IsolationLevel iso, String transactionName)
   at System.Data.SqlClient.SqlConnection.BeginDbTransaction(IsolationLevel isolationLevel)
   at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)
   at System.Data.Entity.Infrastructure.Interception.DbConnectionDispatcher.BeginTransaction(DbConnection connection, BeginTransactionInterceptionContext interceptionContext)
   at System.Data.Entity.Infrastructure.DbExecutionStrategy.Execute[TResult](Func`1 operation)
   at System.Data.Entity.Core.EntityClient.EntityConnection.BeginDbTransaction(IsolationLevel isolationLevel)
****** Inner Exception - END ******
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Error - END ~~~~~~~~~~~~~~~~~~~~~~~~~~


The code is pretty simple:

     public virtual T Add(T entity)
        {
            try
            {
                using (U entityContext = new U())
                {
                    T addedEntity = Add(entity, entityContext);
                    entityContext.SaveChanges();
                    return addedEntity;
                }
            }
            catch (DbEntityValidationException e)
            {
                var msg = FormatDbValidationErrors(e);
                throw new Exception(msg);
            }
            catch (Exception ex)
            {
                AmanLog.Logger.Error(ex);
                throw;
            }
        }


 public virtual T Update(T entity)
        {
            try
            {
                using (U entityContext = new U())
                {
                    T existingEntity = Update(entity, entityContext);
                    entityContext.SaveChanges();
                    return existingEntity;
                }
            }
            catch (DbEntityValidationException e)
            {
                var msg = FormatDbValidationErrors(e);
                throw new Exception(msg);
            }
            catch (Exception ex)
            {
                AmanLog.Logger.Error(ex);
                throw;
            }
        }
1
  • It would be awesome if you could share a minimal reproducible example, including the QueueUserWorkItem code. Commented Jul 18, 2019 at 7:05

1 Answer 1

1

The application handles the files in concurrent threads using ThreadPool.QueueUserWorkItem method.

You can't use the same connection concurrently from two threads, otherwise: this happens. Either:

  • synchronize over a single connection / DB-context, such that it can't be used twice at once (lock would be a simple way to achieve this)
  • use per-work-item connections / DB-contexts, so that nothing is shared
Sign up to request clarification or add additional context in comments.

1 Comment

We not use the same DBContext in different threads, otherwise, the app was not working at all... Each thread initializes the new instance of DbContext. Because of it we can't understand why this error is thrown few times (10-20) each day (the app hadles up to 20K files per day)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.