DataReader在使用LINQ时已经打开
我有一个静态类,它包含一个引用DataContext的包装对象的静态字段。DataReader在使用LINQ时已经打开
当我们创建一个dbml文件时,DataContext基本上由Visual Studio生成&包含我们在数据库中存储的每个存储过程的方法。
我们的类基本上有一堆静态方法,它们触发这些存储的proc方法中的每一个,然后返回一个基于LINQ查询的数组。
例子:
public static TwoFieldBarData[] GetAgesReportData(string pct)
{
return DataContext
.BreakdownOfUsersByAge(Constants.USER_MEDICAL_PROFILE_KEY, pct)
.Select(x => new TwoFieldBarData(x.DisplayName, x.LeftValue, x.RightValue, x.TotalCount))
.ToArray();
}
然后每一个现在,我们得到以下错误:
There is already an open DataReader associated with this Command which must be closed firs
这是间歇性发生的事情,我很好奇,到底是怎么回事。我的猜测是,当一个方法执行和下一个方法之间存在一定的延迟时,它会锁定DataContext并抛出错误。
这是否可能是为了获得排除性而确保其他请求排队等待在lock(){}
中包装DataContext
LINQ调用的每个DataContext
?
DataContext
并不意味着长寿命,绝对不意味着与多个线程一起使用。
静态成员是长期存在的并且可以被多个线程访问。这种冲突可能是你的问题的根源。
锁定数据上下文可能会产生问题,如果不小心的话,它可能会严重影响你的性能或给你造成僵局。
当你的读者循环,虽然记录,然后再尝试运行内的另一个查询命令(例如加载一个分层对象模型)这通常发生
尝试打开添加给这个MultipleActiveResultSets = true参数以您的连接如果可能的话,字符串通常比试图分离你的调用更加干净地解决问题。
http://msdn.microsoft.com/en-us/library/cfa084cz(VS.80).aspx
此外,使用最小的范围内的可能,而单一的“工作单位”的数据上下文如果你愿意。除非你需要维护一些状态,(比如加载一些对象,然后一次保存它们),你不应该重复使用数据上下文。
谢谢迈克,我会给你一个镜头 – 2010-04-22 15:59:06
正如Bryan Watts指出的那样。 DataContext应该是短暂的。确保您只需要在一段时间内使用DataContext。
using(var db = new DataContext())
{
// do your things here!
}
希望它有帮助!
谢谢布莱恩。那么移除包装类并直接在静态方法中直接访问DataContext会更好吗? (而不是存储从DataContext继承的包装的静态引用)? – 2010-04-22 16:05:45
不,你仍然会遇到长寿的'DataContext'问题。相反,您应该完全删除静态API并仅为短期工作单元创建'DataContext'实例。我意识到这可能对您而言不可取或不可取;然而,'DataContext'的设计不支持你的使用场景。 – 2010-04-22 16:18:50