Randomly getting InvalidOperationException: The connection was not closed
See original GitHub issueSeems to happen every now and then for the first few queries after launching an ASPNET5 website. Refreshing the page after crashing <del>almost always</del> <del>sometimes</del> rarely fixes it and I never had an instance where it crashed again after that. I’m using SQL2012. Could this be some sort of race condition?
I’ll try my best to replicate the code I have that causes this exception but it’s hard to give repro steps because this doesn’t happen every time. It does happen about 40% of the time after the website is restarted though.
public class Pet
{
public int Id { get; set; }
public string Name { get; set; }
}
public class PagedPetResult
{
public IAsyncEnumerable<Pet> Pets { get; set; }
public Task<int> TotalPetCount { get; set; }
}
public PagedPetResult GetPets(int pageIndex, int pageSize)
{
var pets = db.Set<Pet>()
.Where(p => p.Id > 0);
var pagedPets = pets
.Skip(pageIndex * pageSize)
.Take(pageSize);
return new PagedPetResult
{
Pets = pagedPets.AsAsyncEnumerable(),
TotalPetCount = pets.CountAsync()
}
}
Now when I call GetPets
using
var pagedPets = GetPets(0, 20);
var foo = new
{
Pets = await pagedPets.Pets.ToList(),
Count = await pagedPets.TotalPetCount,
};
this happens about half of the time. Interestingly, when I change it to:
var pagedPets = GetPets(0, 20);
var pets = await pagedPets.Pets.ToList();
var count = await pagedPets.TotalPetCount;
I haven’t had it crash even once. Could be purely coincidental though…
Stack trace:
InvalidOperationException: The connection was not closed. The connection's current state is connecting.
System.Data.ProviderBase.DbConnectionClosedConnecting.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)
System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
System.Data.SqlClient.SqlConnection.OpenAsync(CancellationToken cancellationToken)
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.Data.Entity.Storage.RelationalConnection.<OpenAsync>d__32.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.Data.Entity.Query.Internal.AsyncQueryingEnumerable.AsyncEnumerator.<MoveNext>d__8.MoveNext()
This might be related to https://github.com/aspnet/EntityFramework/issues/3887
Issue Analytics
- State:
- Created 8 years ago
- Comments:8 (5 by maintainers)
Top GitHub Comments
Hey,
So looking at the original code, you are ending up with two async operations running against the same context at the same time. This is not supported as a DbContext instance is not thread safe. We have https://github.com/aspnet/EntityFramework/issues/3291 currently being worked on to provide a clear exception message when you do this.
The best rule of thumb to apply is to always await an async operation. Applying that rule, you should await the call to
CountAsync
inGetPets
.Here are some more details about what is causing the exception. This line of code in GetPets is kicking off the first async database operation:
Since the async call is not awaited, the code continues one and then the following line kicks of the second database operation.
Since count is a pretty quick operation, it would be sporadic because sometimes the Count operation will complete before the second operation kicks off.
@dealdiane yep, just await the
CountAsync
call and you should be fine.