何时使用IEnumerable将关闭连接

时间:2016-12-26 21:33:58

标签: c# linq lambda linq2db

假设我有一些使用伪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();
}

何时将db关闭连接?在那种情况下它会被关闭吗?将关闭什么连接 - 使用语句或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.物化查询,异常消失了。但是我想知道这件事是如何起作用的。

3 个答案:

答案 0 :(得分:4)

这完全取决于您的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();
  }
}

答案 1 :(得分:0)

第一次通话后

: 在此调用连接中使用范围打开,在usnig范围结束时没有任何提取数据已关闭。

var aItems = GetA();

但是在这一行:

if (!aItems.Any())

没有任何开放连接

答案 2 :(得分:0)

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

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