(I was almost sure we already had an item tracking this but I did a search and I couldn't find it, so I am filing it again. Feel free to resolve as duplicate if you know where the other item is).
EF by default opens and closes the connection for a context as needed. This is not the desired behavior in some cases, e.g.:
- System.Transactions are in use and having multiple open/close can lead to transaction promotion to 2-phase commit or to failures when DTC is not available.
- Additional steps need to be performed whenever the connection is open, e.g. to make sure the connection works correctly, to select the federation member, etc.
- The user prefers to open the connection only once per request.
To address all these scenarios the original design of EF supported a pattern in which the application would take over managing the connection, by simply opening it explicitly, e.g.:
using(var context = new MyObjectContext())
{
using(context.Connection.Open())
{
// the connection will remain open here, i.e. the automatic behavior is turned off
}
}
This behavior was implemented by checking the state of the EntityConnection every time the connection is needed (ObjectContext.EnsureConnection): if it was already open, we should not close it the next time we release it (ObjectContext.ReleaseConnection).
By design, in DbContext we no longer expose the EntityConnection but the underlying database connection on Database.Connection. Unfortunately, the state of the underlying connection and the EntityConnection used by EF to check are not kept in sync. This means that when an application does dbContext.Database.Connection.Open(), the state of the EntityConnection is *not* set to Open, therefore the check we do in EnsureConnection doesn't work.
The workaround currently is to drop down to ObjectContext using IObjectContextAdapter to access the actual EntityConnection. Once you know the pattern it is easy to copy and paste the code, but this is such a fairly common need that it shouldn't be necessary to know about IObjectContextAdapter.
This bug is also related to the ability to pass an already open connection to a context, tracked here:
http://entityframework.codeplex.com/workitem/45
EF by default opens and closes the connection for a context as needed. This is not the desired behavior in some cases, e.g.:
- System.Transactions are in use and having multiple open/close can lead to transaction promotion to 2-phase commit or to failures when DTC is not available.
- Additional steps need to be performed whenever the connection is open, e.g. to make sure the connection works correctly, to select the federation member, etc.
- The user prefers to open the connection only once per request.
To address all these scenarios the original design of EF supported a pattern in which the application would take over managing the connection, by simply opening it explicitly, e.g.:
using(var context = new MyObjectContext())
{
using(context.Connection.Open())
{
// the connection will remain open here, i.e. the automatic behavior is turned off
}
}
This behavior was implemented by checking the state of the EntityConnection every time the connection is needed (ObjectContext.EnsureConnection): if it was already open, we should not close it the next time we release it (ObjectContext.ReleaseConnection).
By design, in DbContext we no longer expose the EntityConnection but the underlying database connection on Database.Connection. Unfortunately, the state of the underlying connection and the EntityConnection used by EF to check are not kept in sync. This means that when an application does dbContext.Database.Connection.Open(), the state of the EntityConnection is *not* set to Open, therefore the check we do in EnsureConnection doesn't work.
The workaround currently is to drop down to ObjectContext using IObjectContextAdapter to access the actual EntityConnection. Once you know the pattern it is easy to copy and paste the code, but this is such a fairly common need that it shouldn't be necessary to know about IObjectContextAdapter.
This bug is also related to the ability to pass an already open connection to a context, tracked here:
http://entityframework.codeplex.com/workitem/45