EF6 has a memory leak in some specific situations. Please look at following code.
```
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
using (var transaction = connection.BeginTransaction())
{
// need to use a lot of small updates instead of one update, because the count of affected records is very big and MemoryOverflow exception can be thrown
for (int i = 0; i < 100; i++)
{
using (var context = new DbContext(connection, false))
{
context.Database.UseTransaction(transaction);
// some updates and inserts
context.SaveChanges();
context.Database.UseTransaction(null);
}
// there is a memory leak.
// all disposed context are stayed in the memory
// the cause of this behavior is attached event handler for the event StateChange on connection
}
transaction.Commit();
}
}
```
If DbContext is created with external connection, then such context will not be disposed, because EntityConnection attached an event handler to the StateChange event in the external connection and this handler is not detached during disposing of DbContext. Therefore GC cannot collect this instance of context.
I use following workaround for this situation.
```
private static void ContextDisposingWorkaround(DbContext context)
{
var connection = context.Database.Connection;
var objectContext = ((IObjectContextAdapter) saveContext).ObjectContext;
ReflectionHelper.RemoveEventHandlers(typeof (DbConnection), "StateChange", "_stateChangeEventHandler", connection,
objectContext.Connection);
}
```
Need to call above method before disposing of context.
Comments: I believe your fix did make it in, as the _stateChangeEventHandler is now null after the DbContext is disposed, previously this was not the case.
But the EntityConnection is definately not disposed when the DbContext is. Other than my observation of memory usage, I'm basing this on the fact that certain properties on the EntityConnection (eg ConnectionString) are populated following dbContext.Dispose(), but then cleared after I make the explicit call to entityConnection.Dipose().
Unfortunately I cannot send my entire source, but I suspect that you are correct that our setups are different.
The setup we're using is somewhat perculiar. We have a single DbConnection in this scenario, each time we iterate we create a new EntityConnection based on this DbConnection:
var entityConnection = new EntityConnection(MetadataWorkspace, dbConnection))
then contstruct a new DbContext using the EntityConnection, eg
new DbContext(entityConnection)
at the end of the iteration the dbConext is disposed (as is the EntityConnection explicitly as a workaround), but the DbConnection lives on.
The reason we do this is so that we can do all this using a single SqlConnection there it can be done transactionally without the need for DTC.
I hope this explanation helps.