【问题标题】:Sub Sonic not closing connections亚音速没有关闭连接
【发布时间】:2010-01-04 02:50:56
【问题描述】:

我正在使用来自 SubSonic 3 的 Linq,如下所示:

for(int x; x < 100; x++) {
   var v = (from c in db.categories
            where c.parent == 10
            select c);

   if (v.Count() > 0) return null;

   category[] c = v.ToArray();
}

由于某种原因,SubSonic 没有关闭连接......所以在运行了几次上述循环后,我用完了池中的 SQL 连接,或者 MySQL 只是拒绝允许更多连接......我都试过了使用 SS 3.0.3 和 SVN,我不断收到这些错误。

在获得一组结果后,我应该怎么做才能关闭连接?

谢谢

【问题讨论】:

  • 尽管我无法回答您的问题,但感谢您向我展示 SubSonic :) 我想我找到了解决问题所需的解决方案。

标签: c# subsonic subsonic3


【解决方案1】:

问题 - 信不信由你 - 不是 SubSonic。它是 $*$&$ MySQL 驱动程序。当您执行这样的查询时,我们会明确关闭连接,但我已经看到 MySQL 驱动程序完全忽略了关闭,而支持一些非常非常糟糕的优化尝试。

我不知道在这里告诉你什么 - 很抱歉。

【讨论】:

  • 我还有另一个离开 MySQL 的理由....不过感谢您的帮助。
【解决方案2】:

MySQL .NET 库似乎存在一些问题。几天前,他们修复了 6.2.2 中与释放连接相关的一些问题。 但是 SubSonic 也有一个问题。我使用 LINQ 模板和 MySQL 来生成我的类。每当 FirstOrDefault() 或 First() (其他类似的函数可能有同样的问题)。

对于如下查询:

var db = new MyDb("CONNECTIONSTRING_NAME");

var userExt = (from pe in db.PhoneExtensions
               where
                   pe.FirstName.ToLower() == firstName.ToLower() &&
                   pe.LastName.ToLower() == lastName.ToLower()
               select pe.Extension).FirstOrDefault();

这将导致查询被执行并且阅读器将不会被释放。

问题出在T方法的Project中的Linq.Structure.DbQueryProvider。

while (reader.Read())
{
    yield return fnProjector(reader);
}
reader.Dispose();

在使用 FirstOrDefault() 和其他类似方法时,永远不会调用 Dispose()。

一个简单的修复:

try
{
    while (reader.Read())
    {
        yield return fnProjector(reader);
    }
}
finally
{
    reader.Dispose();
}

显示问题的简单快速测试:

private class DbDataReader : System.IDisposable
{
    #region IDisposable Members

    public void Dispose() { }

    #endregion
}
private class DbQueryProvider
{
    private DbDataReader _reader;

    public bool IsReaderDisposed { get { return _reader == null; } }

    public DbQueryProvider()
    {
        _reader = new DbDataReader();
    }

    public IEnumerable<int> Project(int numResults)
    {
        int i = 0;
        while (i < numResults)
        {
            yield return i++;
        }
        _reader.Dispose();
        _reader = null;
    }

    public IEnumerable<int> ProjectWithFinally(int numResults)
    {
        int i = 0;
        try
        {
            while (i < numResults)
            {
                yield return i++;
            }
        }
        finally
        {
            _reader.Dispose();
            _reader = null;
        }
    }

}

[Test]
public void YieldReturn_Returns_TrueForIsReaderDisposed()
{
    const int numResults = 1;

    var qp1 = new DbQueryProvider();
    var q1 = qp1.Project(numResults);
    Assert.IsInstanceOf(typeof(int), q1.First());

    var qp2 = new DbQueryProvider();
    var q2 = qp2.Project(numResults);
    Assert.IsInstanceOf(typeof(int), q2.FirstOrDefault());

    var qp3 = new DbQueryProvider();
    var q3 = qp3.Project(numResults);
    Assert.IsInstanceOf(typeof(int), q3.Single());

    var qp4 = new DbQueryProvider();
    var q4 = qp4.Project(numResults);
    Assert.IsInstanceOf(typeof(int), q4.SingleOrDefault());

    Assert.IsTrue(qp1.IsReaderDisposed);
    Assert.IsTrue(qp2.IsReaderDisposed);
    Assert.IsTrue(qp3.IsReaderDisposed);
    Assert.IsTrue(qp4.IsReaderDisposed);
}

[Test]
public void YieldReturnFinally_Returns_TrueForIsReaderDisposed()
{
    const int numResults = 1;

    var qp1 = new DbQueryProvider();
    var q1 = qp1.ProjectWithFinally(numResults);
    Assert.IsInstanceOf(typeof(int), q1.First());

    var qp2 = new DbQueryProvider();
    var q2 = qp2.ProjectWithFinally(numResults);
    Assert.IsInstanceOf(typeof(int), q2.FirstOrDefault());

    var qp3 = new DbQueryProvider();
    var q3 = qp3.ProjectWithFinally(numResults);
    Assert.IsInstanceOf(typeof(int), q3.Single());

    var qp4 = new DbQueryProvider();
    var q4 = qp4.ProjectWithFinally(numResults);
    Assert.IsInstanceOf(typeof(int), q4.SingleOrDefault());

    Assert.IsTrue(qp1.IsReaderDisposed);
    Assert.IsTrue(qp2.IsReaderDisposed);
    Assert.IsTrue(qp3.IsReaderDisposed);
    Assert.IsTrue(qp4.IsReaderDisposed);
}

YieldReturnFinally_Returns_TrueForIsReaderDisposed 通过但 YieldReturn_Returns_TrueForIsReaderDisposed 失败。

我已经在我正在从事的项目上进行了测试,该项目很快就会投入生产,这似乎没有任何问题。使用最大大小为 5 的连接池进行测试,并且没有连接池问题(一次执行 1 个查询时,我的开发机器上的连接永远不会用完)。 我还在 Extensions.Database 中发现了一些与类型更改和分配相关的问题。

我在 github 上 fork 了这个项目,提交了我的更改并提出了拉取请求,希望能找到合适的人。

【讨论】:

    猜你喜欢
    • 2010-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-08
    • 1970-01-01
    • 2018-12-28
    相关资源
    最近更新 更多