Я создаю многопользовательское приложение, используя 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)
Я чувствую какое-то столкновение, пытаясь получить доступ к одному и тому же дб одновременно. Есть идеи?