8

假设我有这样的伪代码使用一些伪 ORM(在我的例子中是 Linq2Db)。

static IEnumerable<A> GetA()
{
  using (var db = ConnectionFactory.Current.GetDBConnection())
  {
     return from a in db.A
            select a;
  }
}
static B[] DoSmth()
{
  var aItems = GetA();
  if (!aItems.Any())
    return null;
  return aItems.Select(a => new B(a.prop1)).ToArray();
}

Connection 什么时候关闭db?在那种情况下它会完全关闭吗?什么连接会被关闭 - using 语句或 lambda 表达式中的连接?.NET 编译器正在为 lambdas 创建匿名类,因此它将复制到该类的连接。该连接何时关闭?

不知何故,我设法让Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.我实现了查询并且异常消失了。但我想知道这件事是如何运作的。

4

3 回答 3

5

这完全取决于您的 ORM。如果处理ConnectionFactory.Current.GetDBConnection()关闭连接,那么您将永远无法枚举结果。如果它没有关闭连接(以及其他东西),它可能会根据其他人是否关闭连接而起作用。

在任何情况下,您可能都不想从创建和处理连接的东西中返回未枚举的可枚举。

在关闭它之前枚举集合,例如:

static IEnumerable<A> GetA()
{
  using (var db = ConnectionFactory.Current.GetDBConnection())
  {
     return (from a in db.A
            select a).ToArray();
  }
}

或在枚举结果的级别控制连接,例如:

static IEnumerable<A> GetA(whatevertype db)
{
   return from a in db.A
          select a;
}
static B[] DoSmth()
{
  using (var db = ConnectionFactory.Current.GetDBConnection())
  {
    var aItems = GetA(db);
    if (!aItems.Any())
      return null;
    return aItems.Select(a => new B(a.prop1)).ToArray();
  }
}
于 2016-12-27T11:42:48.403 回答
1

当您关闭连接对象时,Linq2db 释放连接。在您的示例中,当您离开using块并db处理对象时会发生这种情况。这意味着您无法从连接范围返回查询 - 您需要先获取数据或推迟连接处理,直到您没有获得所有必需的数据。

您观察到的异常是由于 1.8.0 之前的 linq2db 中的错误,它允许在已处置的连接上执行查询,从而导致连接泄漏。有关更多详细信息,请参阅https://github.com/linq2db/linq2db/issues/445。修复后,您将无法编写GetA()示例中的代码,因为您ObjectDisposedException将尝试枚举结果。

于 2018-11-18T16:11:05.450 回答
0

第一次调用后:在此调用连接中使用范围打开,在 usnig 范围关闭时没有任何获取数据。

var aItems = GetA();

但在这一行:

if (!aItems.Any())

没有任何打开的连接

于 2016-12-27T11:29:09.723 回答