即使未关闭连接,临时表也不存在

问题描述

我有以下代码

using (var connection = new sqlConnection(constr))
{
    connection.open();

    var createTempTables = new sqlCommand("[dbo].[p_CreateTempTable]",connection)
    {
        CommandType = CommandType.StoredProcedure
    };

    createTempTables.Parameters.Add(new sqlParameter("@Id",2));
    createTempTables.ExecuteNonQuery();

    var actualCommand = new sqlCommand("[dbo].[p_Test]",connection)
    {
        CommandType = CommandType.StoredProcedure
    };

    var dt = new DataTable();

    dt.Load(actualCommand.ExecuteReader());
}

基本上,[dbo].[p_CreateTempTable]从表中选择与ID inut匹配的行作为参数。然后,[dbo].[p_Test]仅选择临时表。据我了解,临时表应该在连接未关闭的情况下持续存在,但是我总是会收到一个异常,说我的临时表不存在。为什么这不起作用?

注意:如果我改为使用在C#中创建临时表的文本命令,则程序运行没有问题。但是,我想避免这样做,因为在创建临时表时会进行更多的验证,并且由于该应用程序是WinForms,所以我希望避免每次逻辑更改时都重新编译。

解决方法

这里的基本问题是,在SQL Server临时表的生命周期中,绑定到创建它们的批处理和/或会话上下文。

这意味着,如果在存储过程中创建一个临时表,则只有在该存储过程退出之前才能看到该临时表(如此有效,只能由该存储过程调用的其他存储过程)。这是因为存储过程本身就是批处理上下文,因此,如果它创建了一个临时表,则它将绑定到该存储过程的批处理上下文。

只有两种方法可以解决此问题,这两种方法都不方便:

  1. 使用直接命令(即,不在存储过程中)在会话级别创建临时表,这意味着您必须在客户端代码(或配置设置)中包含命令。或者

  2. 改为使用全局临时表。全局临时表实际上不像普通临时表那样工作,它们会在批处理和会话之间持久化,直到您显式删除它们为止,因此可以在存储过程中创建它们并将它们持久化。但是,现在您必须担心与常规表相同的事情:如果表已经存在怎么办?如果有多个用户同时运行此存储过程,该怎么办?与常规表相比,唯一的优点是创建和删除它们所需的特权更少。