当我使用Subsonic ActiveRecord和Sql Server快速添加大量新记录时,我得到了一个熟悉的Timeout SqlException。
超时已过期。超时期限 在获得之前经过了 从游泳池连接。这可能 已经发生,因为所有汇集 连接正在使用和最大池 达到了规模。
我已设法使用以下简单的代码块来复制此问题:
for (int i = 0; i < 1000; i++)
{
var address = new Address();
address.City = "TEST";
address.Save();
}
代码将添加记录,直到达到100(最大池大小,可能不是巧合),此时它会因上述异常而失败。之后,连接将保持5-10分钟左右,在此期间,所有使用数据库的尝试都会产生上述异常。
有趣的是,我发现在VS中的本地计算机上运行此命令(与完全相同的数据库实例相同的代码库)代码成功添加了所有1000条记录。也许这里和我的主机之间的延迟只会减慢数据库调用的速度吗?
鉴于它在本地工作,我认为这不是直接的Subsonic问题,但是我正在制造一些错误,或者我可以改变我的代码或配置来处理添加时连接的快速打开和关闭连续录了很多记录?
答案 0 :(得分:4)
我对AR和SimpleRepo进行了一次性能测试,该测试循环了100,000条记录并且很难打败 - 连接问题确实是进行全局调整时的第一站。
那就是说 - 我们确实在发布前有一个问题,读者被打开了:)。几个月前我修好了 - 所以你能确认你有最新的位吗?
此外 - 是的延迟可能很奇怪。我不知道细节,但看起来就是这样。
答案 1 :(得分:1)
我在使用MySQL时遇到了同样的问题。实例化一个新的活动记录对象然后调用save导致打开一个从未关闭的连接。
找到一个似乎有效的修复程序(感谢kamsar http://github.com/subsonic/SubSonic-3.0/issues#issue/69)显然问题是由于未关闭的Reader?!
更改第197行 SubSonicRepository.cs(3.0.0.3)来 “使用(DbDataReader rdr = provider.ExecuteReader(query))“(和 将使用包装在适当的位置 范围大约像218)似乎有 为我解决了。
所以代码看起来像这样,没有更多的连接泄漏!!!
//var rdr = provider.ExecuteReader(query);
using (System.Data.Common.DbDataReader rdr = provider.ExecuteReader(query))
{
if (rdr.Read())
result = rdr[0];
// repopulate primary key column with newly generated ID
if (result != null && result != DBNull.Value)
{
try
{
var tbl = provider.FindOrCreateTable(typeof(T));
var prop = item.GetType().GetProperty(tbl.PrimaryKey.Name);
var settable = result.ChangeTypeTo(prop.PropertyType);
prop.SetValue(item, settable, null);
}
catch (Exception x)
{
//swallow it - I don't like this per se but this is a convenience and we
//don't want to throw the whole thing just because we can't auto-set the value
}
}
}
答案 2 :(得分:0)
InnerSphere有正确的答案。我无法投票,因为我没有得分,也无法弄清楚如何简单地回复/评论他的帖子。
唯一要添加的是如果您从GitHub中提取代码,则此修复程序已包含在内。
编译和使用从中继代码创建的DLL后没有问题。
答案 3 :(得分:0)
我必须在获得结果后立即添加rdr.Close()
,即:
if (rdr.Read())
result = rdr[0];
rdr.Close();