作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的代码是用 C# 编写的,数据层使用 LINQ to SQL 来填充/加载分离的对象类。
我最近更改了代码以使用多线程,我很确定我的 DAL 不是线程安全的。
你能告诉我 PopCall() 和 Count() 是否线程安全吗?如果不是,我该如何修复它们?
public class DAL
{
//read one Call item from database and delete same item from database.
public static OCall PopCall()
{
using (var db = new MyDataContext())
{
var fc = (from c in db.Calls where c.Called == false select c).FirstOrDefault();
OCall call = FillOCall(fc);
if (fc != null)
{
db.Calls.DeleteOnSubmit(fc);
db.SubmitChanges();
}
return call;
}
}
public static int Count()
{
using (var db = new MyDataContext())
{
return (from c in db.Calls select c.ID).Count();
}
}
private static OCall FillOCall(Model.Call c)
{
if (c != null)
return new OCall { ID = c.ID, Caller = c.Caller, Called = c.Called };
else return null;
}
}
分离的 OCall 类:
public class OCall
{
public int ID { get; set; }
public string Caller { get; set; }
public bool Called { get; set; }
}
最佳答案
它们各自是线程安全的,因为它们使用隔离的数据上下文等。但是,它们不是原子单元。因此,不检查计数是否 > 0 然后假设仍然有东西要弹出是不安全的。任何其他线程都可能改变数据库。
如果你需要这样的东西,你可以包装在一个 TransactionScope
中,它将为你提供(默认情况下)可序列化的隔离级别:
using(var tran = new TransactionScope()) {
int count = OCall.Count();
if(count > 0) {
var call = Count.PopCall();
// TODO: something will call, assuming it is non-null
}
}
当然,这引入了阻塞。最好只检查 FirstOrDefault()
。
请注意,PopCall
仍可能引发异常 - 如果另一个线程/进程在您获取数据和调用 SubmitChanges
之间删除了数据。把它扔在这里的好处是你不应该发现你返回同一条记录两次。
SubmitChanges
是事务性的,但读取不是事务性的,除非跨越事务范围或类似范围。使 PopCall
成为原子而不抛出:
public static OCall PopCall()
{
using(var tran = new TrasactionScope())
using (var db = new MyDataContext())
{
var fc = (from c in db.Calls where c.Called == false select c).FirstOrDefault();
OCall call = FillOCall(fc);
if (fc != null)
{
db.Calls.DeleteOnSubmit(fc);
db.SubmitChanges();
}
return call;
}
tran.Complete();
}
}
现在 FirstOrDefault
被可序列化隔离级别覆盖,所以读取时会锁定数据。如果我们可以在此处显式发出 UPDLOCK
,那将甚至更好,但 LINQ-to-SQL 不提供此功能。
关于c# - LINQ to SQL DAL,这个线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3565212/
我是一名优秀的程序员,十分优秀!