4

当我创建临时表时,我收到一条错误消息,告诉我临时表已经存在。临时表对会话来说是唯一的,所以我的连接似乎没有正确关闭,我认为它可能与我在 using 语句中的 return 语句有关。

我有以下代码:

using (IDbConnection connection = dbConnectionHandler.CreateConnection())
{
   connection.Open();
   CreateATempTable();
   PopulateTempTable();
   DataSet ds = CallStoredProcThatUsesTempTable();
   return ds;
}

我在几个地方使用这种代码来创建一个同名的临时表。

不幸的是,我收到以下错误:There is already an object named '#MyTempTable' in the database.

现在,我知道临时表对于会话是唯一的,因此一旦会话关闭,它就会消失。

我认为有三件事可能会导致这种情况......

  1. 我需要调用 connection.Close()
  2. 我需要将 return 语句放在我的 using 语句之外
  3. 我需要在返回之前删除我创建的临时表

有谁知道它是哪一个?或者如果它是我没有想到的?

4

9 回答 9

6

我在这里猜测,但请检查您的数据库连接池设置。尝试关闭池,看看是否有帮助。

通常,当您在 .NET 库级别关闭/处理连接时,不会关闭真正的数据库服务器连接。它只是返回到数据提供者内部的连接池,当程序请求另一个具有相同参数和凭据的连接时,它将被重用。我认为在返回池之前不会以任何方式重置数据库会话,除了打开的事务和一些基本参数。更昂贵的对象,如临时表,被单独留下。

您可以关闭池化(非常低效)。或者,您可以在尝试创建临时表之前检查它是否存在,如果存在则删除其内容。或者您可以在关闭连接之前删除临时表。

于 2009-02-25T23:49:31.700 回答
3

我很确定将调用 connection.Dispose() (以及 connection.Close() )。

您可以通过执行 1) 和 2) 并检查问题是否仍然存在来轻松验证这一点。解决方案可能是 3),解释是连接池。

于 2009-02-25T23:32:43.380 回答
1

除非发生电源循环或其他一些非常奇怪的角落案例处置将被调用。

如果您想要证明包装对象并在其中放置断点。

于 2009-02-25T23:30:25.633 回答
1

using 块在引擎盖下被转换为 try/catch/finally 块。是的,无论使用块内的返回如何,它都会处理。

于 2009-02-25T23:32:34.363 回答
1

不,connection.Close 将始终被调用,因为内部使用将其放入 try/finally 块中。

您可能还需要考虑连接池。尝试将您的代码包装在 TransactionScope 中。

于 2009-02-25T23:32:53.333 回答
0

在不了解正在使用的数据库连接库的更多信息的情况下,我猜它不是前两个。using专门引入以在退出方法时更容易清理此类资源;它直接类似于try...finallyJava 或类似的普通块。

换句话说,return将离开块并且Dispose将在连接上调用该方法,假设这种情况的合理实现,应该将该Close方法作为该过程的一部分来调用。

这里的关键点是“理智的实施”。

于 2009-02-25T23:32:20.307 回答
0

要回答您的问题:

  1. 当调用连接的 Dispose 方法时,using 语句将隐式关闭连接。
  2. 那应该不需要:http ://aspadvice.com/blogs/name/archive/2008/05/22/Return-Within-a-C_2300_-Using-Statement.aspx
  3. 尝试一下。
于 2009-02-25T23:33:20.180 回答
0

如果对象的类是 IDisposable,即使 using 块中有 return 语句, using 语句也会释放该对象。

它是保持您的#temptable 的连接池,您可能希望手动删除该表。

于 2009-02-25T23:41:30.567 回答
0

这是由连接池引起的。将您正在做的事情包装在事务中,并在最后回滚。或者,在填充 ds 后删除临时表。

于 2009-02-25T23:56:09.923 回答