“提交已在进行中”尝试在 Telerik OpenAccess ORM 中保存更改
Posted
技术标签:
【中文标题】“提交已在进行中”尝试在 Telerik OpenAccess ORM 中保存更改【英文标题】:"A commit is already in progress" attempting to save changes in Telerik OpenAccess ORM 【发布时间】:2013-01-14 08:53:36 【问题描述】:我一直试图弄清楚我的代码中是如何发生错误的。异常告诉我提交已经在进行中,但除非对 SaveChanges
的调用是异步的,否则我看不出这是如何发生的。
我有一个 Scheduler
类,其中包含多个 Task
对象。
每个Task
都有一个BackgroundWorker
,它在另一个线程中进行处理。然后,我在 Task
类中有一个用于此 BackgroundWorker 完成事件的事件处理程序,代码如下:
private void TaskWorkCompleted(object sender, RunWorkerCompletedEventArgs e)
if (!(e.Result is TaskResult))
throw new ArgumentException("Result must be a TaskResult class.");
TaskComplete((TaskResult)e.Result);
还和我在一起吗?所以我在我的任务类中有这个事件处理程序,它触发我在我的主Scheduler
类中使用以下代码处理的事件TaskComplete
:
private void TaskCompleted(object sender, TaskCompletedEvent e)
Model.Task scheduledTask = entitySet.Tasks.First(x => x.TaskName == e.ClassName);
TaskLog logMsg = new TaskLog()
//stuff here
;
scheduledTask.TaskLogs.Add(logMsg);
entitySet.SaveChanges();
现在,据我了解,我回到了我的主线程,因为在我的后台工作程序中完成的工作已经完成。当我有 5 个任务非常频繁地运行时,我在 SaveChanges 上收到一个异常,说提交已经在进行中。我不明白这是怎么回事,因为我没有跨线程共享这个上下文。我可以看到这种情况发生的唯一方法是 SaveChanges 是异步的(不是阻塞调用)。我知道用 using 语句将代码包装在 TaskCompleted 中,新的上下文可以解决它,但我想知道为什么。以及为什么不能在当前状态下工作。
最后一件事,我正在使用 Telerik 的 OpenAccess ORM。
【问题讨论】:
从你的代码中看你是否有 UI 并不明显。这是一个服务器应用程序还是带有用户界面的东西?因为如果您的应用程序没有用户界面,那么 BackgroundWorker 的行为可能会有所不同。 nhibernate 有同样的限制 @RogerN 没有用户界面。它在附近的服务器上连续运行。 @Justin nhiberante 将自动 perform synchronization with database 和 callingcommit
, flush
and other operations from multiple threads is a bug
请修正标题 - 不要将弱假设作为问题发布,而是总结问题。
【参考方案1】:
尝试像这样同步提交:
private static object _syncObject = new object();
private void TaskCompleted(object sender, TaskCompletedEvent e)
Model.Task scheduledTask = entitySet.Tasks.First(x => x.TaskName == e.ClassName);
TaskLog logMsg = new TaskLog()
//stuff here
;
scheduledTask.TaskLogs.Add(logMsg);
lock(_syncObject)
entitySet.SaveChanges();
【讨论】:
【参考方案2】:您可能正在多个线程之间共享DbContext
。
如果您想在多线程环境中使用数据库,最好在开始处理对象之前分离对象(即不使用代理或延迟加载)。然后只需为每个任务创建一个新的DbContext
,附加对象,然后保存更改。
但这会降低速度。如果您想共享DbContext
上下文,您可能应该保留一些计数器,该计数器随每个任务增加,然后在每个任务完成时减少。最后只在计数器再次变为零时保存更改。
【讨论】:
对每个线程一个新的 DBContext 是,对计数引用是不是。以上是关于“提交已在进行中”尝试在 Telerik OpenAccess ORM 中保存更改的主要内容,如果未能解决你的问题,请参考以下文章
在 Telerik 的 RadListView 中预先选择复选框
Telerik WinForm RadGridView清除过滤
在表单数据验证期间防止 Telerik Radbutton 回发
TypeError: com.telerik.widget.gauge.RadRadialGaugeView 不是构造函数