“提交已在进行中”尝试在 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 和 calling commit, 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 Kendo Grid 重新绑定问题

Telerik WinForm RadGridView清除过滤

在表单数据验证期间防止 Telerik Radbutton 回发

TypeError: com.telerik.widget.gauge.RadRadialGaugeView 不是构造函数

制作 作为ReadOnly