DataReader在使用LINQ时已经打开

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并不意味着长寿命,绝对不意味着与多个线程一起使用。

静态成员是长期存在的并且可以被多个线程访问。这种冲突可能是你的问题的根源。

+0

谢谢布莱恩。那么移除包装类并直接在静态方法中直接访问DataContext会更好吗? (而不是存储从DataContext继承的包装的静态引用)? – 2010-04-22 16:05:45

+0

不,你仍然会遇到长寿的'DataContext'问题。相反,您应该完全删除静态API并仅为短期工作单元创建'DataContext'实例。我意识到这可能对您而言不可取或不可取;然而,'DataContext'的设计不支持你的使用场景。 – 2010-04-22 16:18:50

锁定数据上下文可能会产生问题,如果不小心的话,它可能会严重影响你的性能或给你造成僵局。

当你的读者循环,虽然记录,然后再尝试运行内的另一个查询命令(例如加载一个分层对象模型)这通常发生

尝试打开添加给这个MultipleActiveResultSets = true参数以您的连接如果可能的话,字符串通常比试图分离你的调用更加干净地解决问题。

http://msdn.microsoft.com/en-us/library/cfa084cz(VS.80).aspx

此外,使用最小的范围内的可能,而单一的“工作单位”的数据上下文如果你愿意。除非你需要维护一些状态,(比如加载一些对象,然后一次保存它们),你不应该重复使用数据上下文。

+0

谢谢迈克,我会给你一个镜头 – 2010-04-22 15:59:06

正如Bryan Watts指出的那样。 DataContext应该是短暂的。确保您只需要在一段时间内使用DataContext。

using(var db = new DataContext()) 
{ 
    // do your things here! 
} 

希望它有帮助!