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

Reg*_*Guy 0 c# sql-server temp-tables

我有以下代码:

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());
}
Run Code Online (Sandbox Code Playgroud)

基本上,[dbo].[p_CreateTempTable]从表中选择与 ID inut 匹配的行作为参数。然后,[dbo].[p_Test]只需选择临时表。据我所知,只要连接没有关闭,临时表就应该持续存在,但我总是收到一个异常,说我的临时表不存在。为什么这不起作用?

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

RBa*_*ung 5

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

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

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

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

  2. 请改用全局临时表。全局临时表实际上不像普通临时表那样工作,它们将跨批次和会话持续存在,直到您明确删除它们为止,因此您可以在存储过程中创建它们并且它们将持续存在。但是,现在您必须担心与常规表相同的事情:如果这些表已经存在怎么办?如果不止一个用户同时运行这个存储过程怎么办?与常规表相比的唯一优势是创建和删除它们需要较少的权限。