使用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)
我觉得它有点碰撞,试图同时访问同一个数据库。有什么想法吗?
答案 0 :(得分:0)
看起来像在sql server中的锁。许多用户试图同时获得相同的资源。抓住异常,等一下再试一次。
您也可以编写自己的选择程序,例如WITH NOLOCK
或READ UNCOMITED
,并在EF中使用它们。但这可能导致脏读等。