Managing Connections and Transactions
By default, the Entity Framework manages the connection to the database. However, you can manually manage both connections and transactions in your Entity Framework application.
Connections and the Entity Framework
The Entity Framework opens connections only when required, for example to execute a query or to call SaveChanges, and then closes the connection when the operation is complete.
Calling any of the following methods opens the connection:
SaveChanges or Refresh on ObjectContext.
FirstOrDefault, or First on ObjectQuery.
Load on EntityCollection.
Load on EntityReference.
Any Language-Integrated Query (LINQ) method or ObjectQuery query builder method, such as Where, OrderBy, or Select.
|When a query method is called, the connection is opened, and it remains open until the ObjectResult has been completely consumed or disposed.|
Manually Managing Connections
The Entity Framework exposes the EntityConnection through the Connection property. This enables you to manage the connection and transactions or to supply your own EntityConnection. This is useful when you want to hold open a connection within a short-lived object context to improve performance or to explicitly control transactions. The same provider connection used by the Entity Framework can be shared with other parts of an application. The following example shows how to explicitly open a connection:
For more information, see How to: Manually Open the Connection from the Object Context.
When you manually open the connection in a long-running object context, you must call the Dispose method to ensure that the connection is closed when the context is no longer needed. You can also call the Close method on the EntityConnection to explicitly close the connection. For more information, see How to: Manage the Connection in a Long-Running Object Context.
You can also create an EntityConnection and supply this connection to the object context. In this case, you can either open the connection manually or allow the object context to open it when needed. When you have supplied the EntityConnection to the object context, you must ensure that both the context and the EntityConnection are disposed when they are no longer required. The following example creates a connection and passes it to the object context:
// Create an EntityConnection. EntityConnection conn = new EntityConnection("name=AdventureWorksEntities"); // Create a long-running context with the connection. AdventureWorksEntities context = new AdventureWorksEntities(conn);
For more information, see How to: Use EntityConnection with an Object Context.
Considerations for Managing Connections
The following considerations apply when managing connections:
The object context will open the connection if it is not already open before an operation. If the object context opens the connection during an operation, it will always close the connection when the operation is complete.
If you manually open the connection, the object context will not close it. Calling Close or Dispose will close the connection.
If the object context creates the connection, the connection will always be disposed when the context is disposed.
In a long-running object context, you must ensure that the context is disposed when it is no longer required.
If you supply an open EntityConnection for the object context, you must ensure that it is disposed.
Transactions and the Entity Framework
The Entity Framework supports automatic transaction enlistment. This means that activities performed within an object context, such as executing queries and saving changes to data in the data source, can be isolated in the data source by executing the operation within a System.Transactions transaction. Transactions are used in the Entity Framework to do the following actions:
To execute multiple operations against the data source that must be highly consistent, such as queries that depend on the successful completion of object changes.
To coordinate changes in the object context with other distributed operations, such as sending an e-mail notification or writing to a message queue.
Transactions that require the enlistment of additional resource managers are called distributed transactions. Distributed transactions use a distributed transaction coordinator (DTC) to manage the resources that are required to complete the transaction. Promotion of a transaction to a DTC can be a relatively expensive process to establish and complete. Some resource managers, like SQL Server 2005, support the Promotable Single Phase Enlistment (PSPE) transaction protocol. This allows a resource manager to host a transaction that can later be escalated to be managed by the distributed transaction coordinator (DTC) if necessary.
For more information about System.Transactions, see Transaction Processing. For more information about using System.Transactions with SQL Server, see System.Transactions Integration with SQL Server (ADO.NET).
Considerations for Managing Transactions
The following considerations apply when you use transactions with the Entity Framework:
Only operations against the data source are transacted. Changes made to objects in the object context are not transacted. Changes to objects in the context are visible outside the transaction scope.
When you call SaveChanges, if a current transaction exists, the Entity Framework uses this transaction for operations against the data source. Otherwise, it creates a new transaction for the operation. You can define transactions by using EntityTransaction, Transaction, or TransactionScope.
Note: To enlist in an existing transaction, the Entity Framework might close and reopen the connection.
When the Entity Framework creates a new transaction for a SaveChanges operation, changes to objects in the object context are not accepted until the transaction completes. This ensures that the state of the object context and the data source are consistent.
Promotion of a transaction to a DTC may occur when a connection is closed and reopened within a single transaction. Because the Entity Framework opens and closes the connection automatically, you should consider manually opening and closing the connection to avoid transaction promotion. For more information, see How to: Manually Open the Connection from the Object Context.
When you plan to retry operations in a transaction, you must ensure that the status of objects in the context is not reset before the transaction is completed. To do this, you must call SaveChanges with a value of false for the acceptChangesDuringSave parameter, and then call AcceptAllChanges only after other operations in the transaction have completed successfully. For more information, see How to: Manage Transactions in the Entity Framework.
As part of a retry operation with coordinated transactions, you might call SaveChanges a second time without first calling AcceptAllChanges. In this case, the Entity Framework attempts to reapply the same changes to the data source.