为什么我的字典查找会出现 SQL 超时错误?

6

我的应用程序的一部分使用存储在SQL数据库中的道路名称。该应用程序将至少访问每个名称记录一次,大多数记录将被多次访问。因此,我决定将名称数据加载到字典中,然后进行查找以减少数据库读取。

道路名称表有大约300万条记录,我使用以下Linq-to-SQL将其加载到内存中:

Dictionary<String, DbRoadName> roadNames;

using (RoutingDataContext dc = new RoutingDataContext(connectionString))
{
    roadNames = dc.DbRoadNames.ToDictionary(x => x.RoadId);
}

这段代码执行得很好。在此处停止代码并将鼠标悬停在Visual Studio中的roadNames变量上,可以看到字典似乎包含了预期的键值对。

然而,在程序后面的以下行中:

DbRoadName roadName = roadNames[lookupId];

程序出现以下异常:
.Net SqlClient数据提供程序:超时。
据我了解,ToDictionary()方法应该在那一点上执行数据库查询,那么为什么在字典查找时会出现SQL超时错误?
更新: 我通过替换 ToDictionary() 方法中的代码“修复”了问题。
DbRoadName roadName = roadNames[lookupId];

使用TryGetValue语句。然而,我仍然对为什么内存中的字典会产生SQL异常感兴趣。


2
请检查您的 DbRoadName 属性和构造函数。如果在某处缺少值,可能是因为您编写了一个 get 函数以单独获取数据,而数据库没有返回数据。此时,这可能是一个特定的数据错误。 - Spacemonkey
@Blam,DbRoadName是由设计师生成的Linq-to-SQL对象,对应于DbRoadNames表中的一条记录。因此,该字典将该对象作为每个键值对中的值进行保存。 - Steve Bird
1
几乎可以确定是DbRoadNames中的某些内容被延迟执行了。是的,调用ToDictionary将强制执行以获取它们,但不会强制获取所有导航属性。正如Blam所问的那样,什么是DbRoadName?我们知道它是一个对象,并且是来自表格的一条记录,但它是否包含对其他对象的引用? - DrewJordan
既然你已经使用Dispose释放了你的DataContext,我怀疑它不是延迟加载。在这种情况下,我会期望出现空引用异常而不是超时,因为当你的DataContext消失后就不能再进行加载了。 - Pleun
DbRoadName roadName = roadNames[lookupId]; 是否在 using() 内部? - flaudre
显示剩余14条评论
1个回答

1
为避免 SQL 超时,我不会在字典中加载 Storage-Model。相反,使用必要属性将数据作为 Model 加载,如下所示:
Dictionary<String, DbRoadNameModel> roadNameModelDictionary;
using (RoutingDataContext dc = new RoutingDataContext(connectionString))
{
    roadNames = dc.DbRoadNames
        .Select(roadName => new DbRoadNameModel(roadName.RoadId, roadName.Prop1, roadName.Prop2))
        .ToDictionary(x => x.RoadId);
}

这有帮助吗?

我做了非常类似的事情,使用一个非常简单的新poco对象来保存字典中的数据。令我惊讶的是,即使字典中没有包含任何数据库对象,我仍然在访问字典时遇到了SQL超时问题。 - Steve Bird
你尝试过来自Steffenn Winkler或Flaudre的建议吗?在using语句内访问字典中的元素。也许usr是正确的,异常是误导性的。 - gReX

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接