Ошибка ожидающих запросов Entity Framework - PullRequest
0 голосов
/ 03 февраля 2012

Я создаю многопользовательское приложение, используя 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 голосов
/ 03 февраля 2012

Похоже на блокировку на сервере sql.Многие пользователи пытаются получить один и тот же ресурс одновременно.Перехватите исключение, подождите и повторите попытку.

Вы также можете написать свои собственные процедуры выбора, например WITH NOLOCK или READ UNCOMITED, и использовать их в EF.Но это может вызвать грязное чтение и т. Д.

...