1

when I am trying to pull records in a async Task function from table using Unit of work repo, facing an exception

"System.Data.Entity.Core.EntityException: The underlying provider failed on Open. ---> System.InvalidOperationException: The connection was not closed. The connection's current state is connecting."

var ProductList= unitOfWork.ProductRepo.Find(x => x.Id== ProductId);

although I am creating a new object of unitofwork for each Task. but for a single thread, it works fine.

  full trace:"TRACE:Task.Execute => Task`1.InnerInvoke => <>c__DisplayClass17_0.<StartMigration>b__0
           EXCEPTION:System.Data.Entity.Core.EntityException: The underlying provider failed on Open. ---> System.InvalidOperationException: The connection was not closed. The connection's current state is connecting.
     at System.Data.ProviderBase.DbConnectionClosedConnecting.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
     at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)
     at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
     at System.Data.SqlClient.SqlConnection.Open()
     at System.Data.Entity.Infrastructure.Interception.DbConnectionDispatcher.<Open>b__36(DbConnection t, DbConnectionInterceptionContext c)
     at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext](TTarget target, Action`2 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)
     at System.Data.Entity.Infrastructure.Interception.DbConnectionDispatcher.Open(DbConnection connection, DbInterceptionContext interceptionContext)
     at System.Data.Entity.Core.EntityClient.EntityConnection.<Open>b__2()
     at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.<>c__DisplayClass1.<Execute>b__0()
     at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation)
     at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute(Action operation)
     at System.Data.Entity.Core.EntityClient.EntityConnection.Open()
     --- End of inner exception stack trace ---
     at System.Data.Entity.Core.EntityClient.EntityConnection.Open()
     at System.Data.Entity.Core.Objects.ObjectContext.EnsureConnection(Boolean shouldMonitorTransactions)
     at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
     at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__5()
     at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation)
     at System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
     at System.Data.Entity.Core.Objects.ObjectQuery`1.<System.Collections.Generic.IEnumerable<T>.GetEnumerator>b__0()
     at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()
     at System.Linq.Enumerable.Count[TSource](IEnumerable`1 source)
     at FS.Migration.Assistant.Assistant.MigrationAssistance.<>c__DisplayClass17_0.<<StartMigration>b__0>d.MoveNext() in "

not all code I can paste , here is the piece of code where am craeting new connection using DBconrtext for each time Task runs

  Task.Run(async () =>
            {

                Model.MigrationModel.ReadyToMigrate ready = new ReadyToMigrate();
                unitOfWork = new UnitOfWork(new ContextMigrationEntities());
                try
                {
}Catch(Exception ex)
{
}
});
  • Post the *full* exception, including its call stack. You can get this easily with `Exception.ToString().` The code posted here doesn't help at all, except to show that you *don't* have any tasks. – Panagiotis Kanavos Nov 29 '18 at 11:28
  • 4
    Did you try to use the *same* context, ie the *same* connection from different threads perhaps? *Why*? It won't make things run faster. In this case something is trying to call `Open` on a connection that's already trying to connect. If you want to load multiple objects use `.Where(x=>listOfProducts.Contains(x.Id)).ToListAsync()` – Panagiotis Kanavos Nov 29 '18 at 11:30
  • @PanagiotisKanavos no, I am using different dbcontext object for each task or thread, for that am facing this exception – Pramod Harlapur Nov 29 '18 at 11:34
  • 2
    Post the *actual* code that creates the tasks and the contexts. Something ends up using the same connection. Why *tasks* anyway when you already have asynchronous operations? – Panagiotis Kanavos Nov 29 '18 at 11:38
  • And post the **FULL** exception text, not just the call stack. The full text includes inner exceptions. BTW that call stack doesn't match your code. Somehow, somewher you call a `Count()` – Panagiotis Kanavos Nov 29 '18 at 11:39
  • I can only use the wrapper functions used in unit of work, like FInd, insert,update etc. where this ToListAsync() came from, in my Linq not able to find it – Pramod Harlapur Nov 29 '18 at 11:41
  • var ProductList= unitOfWork.ProductRepo.Find(x => x.Id== ProductId); if(ProductList!=null && ProductList.Count()>0) { } – Pramod Harlapur Nov 29 '18 at 11:42
  • In `FS.Migration.Assistant.Assistant.MigrationAssistance` you are calling a `Count()`. The code you posted here doesn't have anything like that. Post the *actual* code that throws. And don't use tasks, EF has async methods. If you use a wrapper that prevents you from properly using EF, fix the wrapper. It would seems it has thread-safety issue that go beyond preventing you from properly making asynchronous calls. By using a Task on top of a blocking call you waste *two* threads waiting for the results. With proper async methods, you wouldn't need even one – Panagiotis Kanavos Nov 29 '18 at 11:43
  • @PanagiotisKanavos here is the bit of exact code, I just modified earlier var readyToMigrateList = unitOfWork.Ready_TO_Migrate.Find(x => x.Client_Id == clientId); if (readyToMigrateList != null && readyToMigrateList.Count() > 0) { – Pramod Harlapur Nov 29 '18 at 11:45
  • 1
    Without your actual coce, one can only guess what's going on. You can't know whether it uses the same *DbContext* or reuses the same database connection. It's impossible to know whether you use the same injected context or not. Unit Of Work is a completely different concept from Repository anyway. The only thing that's certain is that the code *does* try to use the same context from different threads – Panagiotis Kanavos Nov 29 '18 at 11:48
  • One guess is that the connection object itself is injected. Perhaps someone thought that opening/closing connections is expensive and a common connection would help. On the contrary, that causes *significant* performance problems by holding locks for the duration of the connection. It doesn't help with opening a connection either - most ADO.NET providers use connection pooling to reset and reuse existing connections. That's why connections are declared inside `using` blocks in tutorials – Panagiotis Kanavos Nov 29 '18 at 11:54
  • It tells you that EF is not thread-safe. [Look here](https://stackoverflow.com/questions/4455634/entity-framework-thread-safety). – Hans Passant Nov 29 '18 at 12:01
  • @PanagiotisKanavos ya you are right, EF is not a thread safe. but do I need to change the structure ? – Pramod Harlapur Nov 29 '18 at 12:12

0 Answers0