2016-11-15 392 views
1

我工作的一个非常大的项目,这是应该跟一个很老的指挥基地API,并进行大量的行动,他们每个人都必须执行许多命令来获得到了这一点,然后我必须保存结果的状态。如何避免的DbContext问题在多线程方案

大家会谈到我的数据库,他们添加一条记录到我的进程队列,我读它,执行一些动作,返回无论是在排队的过程本身或受人尊敬的表中的一些结果。

主管道如下图所示,我省略了很多动作和锁。 enter code here

DB是EF DbContext,黑盒子,是在主线程中运行的动作,它运行多个动作并反复执行,直到应用程序终止。

橙盒,是子线程谁执行的操作后,他们被主线程调用。

以前我有1个问题,数据库由于事务而死亡,但是因为必须在我的队列中有1个API或者至多2个,我只觉得它在SQL管理工具下,所以我想稍后修复它。

,但新的,我觉得这个问题一段时间了,但今天我看到了,......我有一个失败的动作,然后应用程序开始重复同样的过程,一遍又一遍,而不终止它或做任何其他,但它应该返回成功或错误。所以我跟踪了一会儿,我注意到它是失败的地方(内部异常处理程序之一),它说我试图插入一个重复的密钥到数据库中,所以我去看看Db的变化,我注意到我有超过五个条目,这应该只有一个。

,所以我首先想到的每一个dB.SaveChange之前得到改变乘坐的,所以我就在网上找到了一些代码段这使得所有的变化保持不变。 所以我开始改变我的应用程序添加这段代码:

lock(DbAction){ 
    ClearingDbContextChanges(); 
    AddResults() if there is any 
    Change() if there is any 
    Delete() if there is any 
    SetEntity as Modified if there is any 
    Db.SaveChanges() 
} 

然后之前,我跑我到达最后一个景点,在那里我发现我不能再使用此应用程序的运行,并呈现一些我的主要行动无法使用。

+0

“如何避免多线程场景中的DbContext问题”>不要重复使用来自多个线程的相同DbContext - 每次需要时创建新的DbContext。 – Evk

+0

当数据库对它们进行事务锁定时,访问相同数据会不会导致更多的麻烦? – deadManN

+2

我会说它永远不会创建更多的问题,从多个线程重用相同的DbContext - 这是一个真正的禁忌。 – Evk

回答

0
lock(DbAction) { 
    // Modify DB 
} 

混合应用程序锁和DB锁。你正在寻求一个无法察觉的僵局。锁定等待链有周期时发生死锁。数据库能够检测这些周期并解决死锁(通过选择受害者并中止其事务)。但是,当您像应用程序锁和数据库锁一样组合时,等待链可以通过应用程序锁形成一个循环。认为线程A持有数据库锁1并等待DbAction,线程2持有DbAction并等待数据库锁1.这些死锁链是由DB无法检测到的,因此没有发生死锁。你的应用程序将永远保持僵局(直到明确杀死)。

同时保持应用程序lock不要发出DB电话。决不。永远。

现在,针对您的问题:您展示典型的ACID不一致问题。您的工作单元似乎反复执行(数据库中的重复条目)和/或在数据库中保存不一致的状态(缺少事务处理范围?)。人们无法猜测那里有什么问题。

+0

好吧,我不想锁定数据库,我希望它被解锁,但我需要交易继续下去,如果某件事失败了,这个项目是那些炸毁的那个,所以我需要定义它们。我介绍Locks不是为了控制数据库,我想,但是你恢复了那部分。我只用它们来管理,哪些池项目应该通过并跟踪活动/非活动会话。也跟踪队列项目,完全可以说我管理我的处理流程,并且整个大约1年我在这个系统上工作,我似乎没有造成任何死角。 – deadManN

+0

嗯,我仍然没有在同一时间启动如此多的池对象和请求,因为它是所有的测试和调试,但我认为我的系统没有太多的bug,我比那更害怕RCW异常,因为API只能在Windows窗体上运行,并且它应该是同步的,我以某种方式将它拿出来交易,但仍然无法处理。 – deadManN