我正在使用 NServiceBus 构建一个系统,而我的 DataLayer 正在使用 Linq 2 SQL。
该系统由 2 个服务组成。
Service1 从 NSB 接收消息。它将在我的数据库中查询 Table1 并将记录插入 Table1 如果满足某个条件,则将新的 NSB 消息发送到第二个服务
当 Service2 接收到来自 Service1 的消息并执行其他一些与数据库无关的工作时,它也会更新 Table1 中的记录。Service2 是一个长时间运行的进程。
我遇到的问题是 Service2 更新 Table1 中的记录时,该表被锁定。在 Service2 完成所有处理之前,锁似乎就位。即我的数据上下文被释放后,锁没有被释放。
这会导致 Service1 中的查询超时。一旦 Service2 完成处理,Service1 将再次恢复处理而不会出现问题。
因此,例如 Service1 代码可能如下所示:
int x =0;
using (DataContext db = new DataContext())
{
x = (from dp in db.Table1 select dp).Count(); // this line will timeout while service2 is processing
Table1 t = new Table1();
t.Data = "test";
db.Table1.InsertOnSubmit(t);
db.SubmitChanges();
}
if(x % 50 == 0)
CallService2();
service2 中的代码可能如下所示:
using (DataContext db = new DataContext())
{
Table1 t = db.Table1.Where(t => t.id == myId);
t.Data = "updated";
db.SubmitChanges();
}
// I would have expected the lock to have been released at this point, but this is not the case.
DoSomeLongRunningTasks();
// lock will be released once service2 exits
我不明白为什么在Service2中处理datacontext时没有释放锁。
为了解决我一直在打电话的问题:
db.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
这行得通,但我不喜欢使用它。我想正确解决这个问题。
以前有没有人遇到过这种问题,有人知道如何解决吗?为什么数据上下文被释放后锁没有被释放?
提前致谢。
ps 很抱歉这篇文章太长了。
编辑:
在现实世界(ish)的情况下看这个,比如运输:
service1 将 crate 记录添加到数据库中。如果存在特定数量或板条箱记录,则将板条箱添加到容器记录(如果不存在容器记录,则创建一个),然后创建运输记录并关闭所有容器并分配给运输记录。
然后调用 service2 处理运输记录。对 service2 的调用是 Bus.Send 调用,但可能是传奇的一部分。service2 将更新每个 crate 记录,它被分配到哪个船。然后处理一些其他的运输指令。当 service2 正在处理时,可能会收到更多的 crate 用于下一次运输,但就目前而言,在 service2 完成运输处理之前,它们不能分配到容器中。