实体框架待处理请求错误

时间:2012-02-03 14:07:34

标签: c# sql-server entity-framework-4 transactions backgroundworker

使用EF4构建多用户应用程序。一个用户正在进行更改而其他用户无法看到更改,因此我的解决方法是:

1。我在我的数据库中创建了一个表,并查看了它(RecentUpdates),它获得了所有用户所做的最后20秒的更改(包括自己的更改)。

2. 我检索后台工作线程内的最新更改(每15秒)并尝试更新已更改的本地数据:

    private void dbUpdater_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
    {
        while (true)
        {
                var recentUpdates = Helper.Ctx.RecentUpdates;
                foreach (RecentUpdate ru in recentUpdates)
                {
                    switch (ru.Table)
                    {
                        case "Trailers":
                            Helper.Ctx.Refresh(RefreshMode.ClientWins, Helper.Ctx.Trailers.Where(x => x.Id == ru.Id));
                            break;
                        case "Bookings":
                            Helper.Ctx.Refresh(RefreshMode.ClientWins, Helper.Ctx.Bookings.Where(x => x.Id == ru.Id));
                            Helper.Ctx.Refresh(RefreshMode.ClientWins, Helper.Ctx.Planner.Where(x => x.Id == ru.Id));
                            break;
                        case "Works":
                            Helper.Ctx.Refresh(RefreshMode.ClientWins, Helper.Ctx.Works.Where(x => x.Id == ru.Id));
                            break;
                        case "Requests":
                            Helper.Ctx.Refresh(RefreshMode.ClientWins, Helper.Ctx.Requests.Where(x => x.Id == ru.Id));
                            break;
                    }
                }
                System.Threading.Thread.Sleep(15000);
        }
    }

3。用户正在进行更改,并且后台线程正在接收,有时会导致以下错误:

System.Data.EntityException: The underlying provider failed on Commit. ---> System.Data.SqlClient.SqlException: The transaction operation cannot be performed because there are pending requests working on this transaction.
   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.SqlInternalTransaction.Commit()
   at System.Data.SqlClient.SqlTransaction.Commit()
   at System.Data.EntityClient.EntityTransaction.Commit()
   --- End of inner exception stack trace ---
   at System.Data.EntityClient.EntityTransaction.Commit()
   at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)
   at System.Data.Objects.ObjectContext.SaveChanges()
   at CAPS.fMain.dgvBookings_CellClick(Object sender, DataGridViewCellEventArgs e)
   at System.Windows.Forms.DataGridView.OnCellClick(DataGridViewCellEventArgs e)
   at System.Windows.Forms.DataGridView.OnMouseClick(MouseEventArgs e)
   at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.DataGridView.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

还有:

************** Exception Text **************

System.Data.EntityException: An error occurred while starting a transaction on the provider connection. See the inner exception for details. ---> System.Data.SqlClient.SqlException: New transaction is not allowed because there are other threads running in the session.

   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)

   --- End of inner exception stack trace ---

   at System.Data.EntityClient.EntityConnection.BeginDbTransaction(IsolationLevel isolationLevel)

   at System.Data.EntityClient.EntityConnection.BeginTransaction()

   at System.Data.Objects.ObjectContext.SaveChanges(SaveOptions options)

   at System.Data.Objects.ObjectContext.SaveChanges()

   at CAPS.fMain.dgvBookings_CellClick(Object sender, DataGridViewCellEventArgs e)

   at System.Windows.Forms.DataGridView.OnCellClick(DataGridViewCellEventArgs e)

   at System.Windows.Forms.DataGridView.OnMouseClick(MouseEventArgs e)

   at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)

   at System.Windows.Forms.Control.WndProc(Message& m)

   at System.Windows.Forms.DataGridView.WndProc(Message& m)

   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)

   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)

   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

我觉得它有点碰撞,试图同时访问同一个数据库。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

看起来像在sql server中的锁。许多用户试图同时获得相同的资源。抓住异常,等一下再试一次。

您也可以编写自己的选择程序,例如WITH NOLOCKREAD UNCOMITED,并在EF中使用它们。但这可能导致脏读等。