【发布时间】:2015-11-20 11:08:16
【问题描述】:
我有一个多线程环境,每个线程都想在表中选择一行(如果不存在则插入)并在其中增加一些内容。
基本上,每个线程都会做这样的事情:
using (var context = new Entity.DBContext()) {
if(!context.MyTable.Any(...)) {
var obj = new MyTable() {
SomeValue = 0
};
context.MyTable.Add(obj)
}
var row = context.MyTable.SingleOrDefault(...);
row.SomeValue += 1;
context.SaveChanges();
}
示例中的问题:特定行的 SomeValue = 0。 两个线程同时选择这个特定的行,它们都看到 0。 -> 它们都将其递增一次,SomeValue 中的最终结果将为 1,但我们希望它为 2。
我假设在另一个之后到达的线程应该等待(使用锁?)第一个结束。但是我不能让它正常工作。
谢谢。
【问题讨论】:
-
确认 - 您使用的是什么数据库系统?这可能应该在 SQL 级别解决。
-
我同意 Damien_The_Unbeliever 的观点。您应该使用RowVersion 来确保原子访问。
-
我使用 EntityFramework 和 SQL-Server。
-
您看到的问题是 EF 使用单独的读/写语句并且没有可序列化的事务。如果您真的只是将字段增加 +1,那么最好使用 SP(或直接 SQL 语句)在单个更新语句中完全执行此操作。如果您尝试在实体读/写周围包装可序列化的 TX,通常会发生死锁。
标签: c# sql sql-server multithreading entity-framework