这是一个代码片段:
private static ApplicationParameter TryGet(MyDataContext ctxt, string parameterName) {
return ctxt.GetTable<ApplicationParameter>().Where(p => p.Name.ToLower() == parameterName.ToLower()).SingleOrDefault();
}
private static Dictionary<string, string> _cache = new Dictionary<string, string>();
public static string GetValue(string parameterName) {
if (!_cache.ContainsKey(parameterName))
using (var ctxt = new MyDataContext()) {
var ap = TryGet(ctxt, parameterName);
if (ap != null)
_cache[parameterName] = ap.Value;
else
_cache[parameterName] = null;
}
return _cache[parameterName];
}
这段代码大部分时间都可以正常工作。然而,在负载测试中,我们有时会在TryGet()
方法中遇到臭名昭著的“Open DataReader”错误,调用堆栈显示它通过了GetValue()
。
对于我的一生,我看不出这是怎么可能的。我显然using
在调用周围使用了一个块TryGet
,带有一个新实例MyDataContext
,并且只有一个查询。那么那里怎么可能DataReader
已经有一个开放空间呢?
MyDataContext
除非...... (显然继承自)的所有实例之间存在一些共享连接DataContext
,并且当两个线程同时尝试使用该Connection
属性时,即使是两个不同的数据上下文,不知何故它们都在访问相同的DataReader
?
这可能是真的吗?还能有什么其他解释?
编辑:我在OnCreated
方法中放置了一个记录器,MyDataContext
并记录了GetHashCode
数据上下文及其Connection
属性的值。那里没有重复,所以我猜他们没有共享同一个对象 - 至少,不是在正常使用中。自安装日志以来,没有看到“打开数据读取器”错误。但即使他们没有使用相同的连接对象,也许他们仍然以某种方式共享与数据库的相同连接?