“提交已在进行中”尝试保存Telerik OpenAccess ORM中的更改

时间:2013-01-30 13:55:29

标签: c# .net multithreading orm telerik-open-access

我一直试图弄清楚我的代码中是如何发生错误的。异常告诉我提交已在进行中,但除非对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);
}

还在我身边吗?所以我在我的任务类中有这个事件处理程序,它使用以下代码触发我在主TaskComplete类中处理的事件Scheduler

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。

2 个答案:

答案 0 :(得分:0)

尝试同步这样的提交:

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();
    }
}

答案 1 :(得分:0)

您可能在多个主题之间共享DbContext

如果您想在多线程环境中使用数据库,那么在开始处理对象之前分离对象(即不使用代理或延迟加载)可能会更好。然后,只需为每个任务创建一个新的DbContext,附加该对象,然后保存更改。

然而,这会降低速度。如果您想共享DbContext上下文,您应该保留一些计数器,该计数器会因每项任务而增加,然后在每项任务完成时减少。最后,只有在计数器再次达到零时才保存更改。