Entity Framework provides concurrent database access == EntityException

concurrency entity-framework multithreading sql wcf

Question

For data update/retrieval, I have an MS SQL 2008 database that is accessible by LINQ.

WCF services use a PerCall instantiation mode to access my linq for a demanding application. This program is running many applications at once and has multiple threads that contact the service.

I experience EntityExceptions frequently:

System.Data.EntityException was caught Message=An error occurred while starting a transaction on the provider connection. See the inner exception for details. Source=System.Data.Entity StackTrace: at System.Data.EntityClient.EntityConnection.BeginDbTransaction(IsolationLevel isolationLevel) at System.Data.EntityClient.EntityConnection.BeginTransaction() at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options) at Infoteam.GfK.TOMServer.DataServer.DataServer.SaveChanges() in D:\Workspace\XYZWASDF\DataServer\DataServer.cs:line 123 InnerException: System.Data.SqlClient.SqlException Message=Une nouvelle transaction n'est pas autorisée parce que d'autres threads sont en cours d'exécution dans la session. Source=.Net SqlClient Data Provider ErrorCode=-2146232060 Class=16 LineNumber=1 Number=3988 Procedure="" Server=ift-srv114 State=1 StackTrace: at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning() at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) at System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj, Boolean isDelegateControlRequest) at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransactionYukon(TransactionRequest transactionRequest, String transactionName, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest) at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransaction(TransactionRequest transactionRequest, String name, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest) at System.Data.SqlClient.SqlInternalConnection.BeginSqlTransaction(IsolationLevel iso, String transactionName) at System.Data.SqlClient.SqlInternalConnection.BeginTransaction(IsolationLevel iso) at System.Data.SqlClient.SqlConnection.BeginDbTransaction(IsolationLevel isolationLevel) at System.Data.Common.DbConnection.BeginTransaction(IsolationLevel isolationLevel) at System.Data.EntityClient.EntityConnection.BeginDbTransaction(IsolationLevel isolationLevel) InnerException:

(Sorry, it's hard to read.) ( "A new transaction is not authorized because there are other threads active in the session," states the message of the internal error.

I've verified that I'm not in a loop, that this exception is always made at random, and that I have no clue how to stop it.

Any assistance would be much appreciated.

I'm grateful.

EDIT: Here is an illustration of how I encountered this error. SOMETIMES

    //My DataServer method, which is a singleton

    [MethodImpl(MethodImplOptions.Synchronized)]
            public void SaveChanges()
            {
                lock (_lockObject)
                {
                    try
                    {
                        _context.SaveChanges(SaveOptions.AcceptAllChangesAfterSave);
                        _changeListener.ManageIDAfterInsert();                       
                    }
                    catch (Exception ex)
                    {
                        Logger.Instance.Error("[DataServer:SaveChanges] Got an error when trying to save an object", ex);
                        //HERE I've this error
                    }
                }
            }

//One example where I can have exception sometimes, this is called through a WCF service, so I have a method which attach the object and then save it
private OrderStatus AddOrderStatus(OrderStatus orderStatus)
        {
            DataServer.DataServer.Instance.InsertOrUpdateDetachedObject(orderStatus);

            return orderStatus;
        }
1
8
3/2/2011 8:32:56 AM

Accepted Answer

The simple answer is that EntityFramework is not thread-safe without viewing your code. This issue occurs when two or more threads overlap while you are attempting to access yourObjectContext . You must have crammed your context into astatic variable. Make the context a local variable or create locking to prevent unauthorized access.ObjectContext .

Posting your code will be helpful if you need a more detailed response.

Edit

Your problem is that there are now two threads attempting to utilize the context concurrently, or that one thread is leaving a transaction open while a second thread attempts to use the singleton context at the same time. I now have more questions than I had before after reading your code sample.

  • The in your code samplelockObject an immovable variable?
  • Why are you displaying the lock?SaveChanges Nonetheless, clarify that an error is coming fromInsertOrUpdateDetachedObject ? Can we see the source code forInsertOrUpdateDetachedObject ?
  • Uses the same methods as SaveChanges_lockObject as all other techniques that directly access the context?
  • Are you calling to_context.SaveChanges the sole method you use to save data to the database, or do you have additional places that automatically initiate transaction contexts?
  • Because you are utilizing a singleton, your context is shared by all of your calls. For each WFC call, it could be desirable to create a fresh new context.
7
3/2/2011 1:51:19 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow