ExecuteNonQuery не работает для создания TempTable SQL Server - PullRequest
2 голосов
/ 03 июля 2019

Временная таблица не создается в базе данных.Я проверил, что учетные данные имеют доступ для создания временной таблицы.Скопируйте и вставьте команду SQL, и она работает в SSMS.

При отладке не генерируются исключения.Переменная cmd имеет правильное соединение и текст SQL перед выполнением.

Я использовал эту же строку соединения в других частях приложения для успешного запроса к серверу, поэтому проблем там нет.

Моя цель - создать временную таблицу, затем заполнить ее с помощью SqlBulkCopy, затем выполнить обновление слиянием, а затем удалить временную таблицу.

РЕДАКТИРОВАТЬ: Моя ошибка ссылалась на неправильную таблицу в DestinationTableName, но, тем более, что я былпроверка прогресса в SSMS с отдельным соединением, которое не может видеть временную таблицу.Кроме того, оператор finally является излишним.Спасибо всем!

        string tmpTable = @"create table #TempTable 
                            (
                            [Column1] [varchar](50) NOT NULL,
                            [Column2] [varchar](50) NOT NULL,
                            [Column3] [varchar](50) NOT NULL
                            )";
        string connString = "Data Source=AzureDBServer;" + 
                                "Initial Catalog=Database;" + 
                                "User id=UserId;" + 
                                "Password=Password;";

        using (SqlConnection connection = new SqlConnection(connString))
        {
            connection.Open();
            SqlCommand cmd = new SqlCommand(tmpTable, connection);
            cmd.ExecuteNonQuery();

            try
            {
                using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
                {
                    bulkCopy.DestinationTableName = "#TempTable";
                    bulkCopy.WriteToServer(dataTable);

                    string mergeSql = "<Will eventually have merge statement here>";

                    cmd.CommandText = mergeSql;
                    int results = cmd.ExecuteNonQuery();

                    cmd.CommandText = "DROP TABLE #TempTable";
                    cmd.ExecuteNonQuery();
                }
            }
            catch (Exception)
            {
                throw;
            }

            finally
            {
                SqlCommand final = new SqlCommand("DROP TABLE #TempTable", connection);
                final.ExecuteNonQuery();

            }

        }

Ответы [ 2 ]

3 голосов
/ 03 июля 2019

Я проверяю в SSMS, используя те же учетные данные, получаю ошибку «Недопустимое имя объекта« #TempTable »» после завершения кода

Это потому, что SSMS использует различное соединение , а временные таблицы, такие как #Foo: на соединение .Вы не можете получить доступ к #Foo таблице темпов из любого другого соединения.

Звучит так, как будто вам нужна глобальная таблица темпов.Это так же просто, как назвать его ##Foo вместо #Foo.Глобальные временные таблицы являются общими для всех соединений.

0 голосов
/ 03 июля 2019

Проблема заключается в простой опечатке, как @MarcGravell указал в комментарии.

bulkCopy.DestinationTableName = "TempTable";

должно быть

bulkCopy.DestinationTableName = "#TempTable";

Временные таблицы имеют время жизни сеанса, если они не созданы во вложенном пакете или хранимой процедуре.

Например, это работает:

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace sqlclienttest
{
    class Program
    {
        static void Main(string[] args)
        {
            string tmpTable = @"create table #TempTable 
                                (
                                [Column1] [varchar](50) NOT NULL,
                                [Column2] [varchar](50) NOT NULL,
                                [Column3] [varchar](50) NOT NULL
                                )";
            string connString = "Data Source=xxxx.database.windows.net;" +
                                    "Initial Catalog=Adventureworks;" +
                                    "User id=xxxxxx;" +
                                    "Password=xxxxxx;";

            var dataTable = new DataTable();
            dataTable.Columns.Add("Column1", typeof(string));
            dataTable.Columns.Add("Column2", typeof(string));
            dataTable.Columns.Add("Column3", typeof(string));

            dataTable.BeginLoadData();
            for (int i = 0; i < 10000; i++)
            {
                var r = dataTable.NewRow();
                r[0] = $"column1{i}";
                r[1] = $"column2{i}";
                r[2] = $"column3{i}";
                dataTable.Rows.Add(r);
            }
            dataTable.EndLoadData();

            using (SqlConnection connection = new SqlConnection(connString))
            {
                connection.Open();
                SqlCommand cmd = new SqlCommand(tmpTable, connection);
                cmd.ExecuteNonQuery();

                try
                {
                    using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
                    {
                        bulkCopy.NotifyAfter = 1000;
                        bulkCopy.SqlRowsCopied += (s, a) => Console.WriteLine($"{a.RowsCopied} rows");
                        bulkCopy.DestinationTableName = "#TempTable";
                        bulkCopy.WriteToServer(dataTable);

                        //string mergeSql = "<Will eventually have merge statement here>";

                        //cmd.CommandText = mergeSql;
                        //int results = cmd.ExecuteNonQuery();

                        cmd.CommandText = "DROP TABLE #TempTable";
                        cmd.ExecuteNonQuery();
                    }
                }
                catch (Exception)
                {
                    throw;
                }


            }
        }
    }
}

Единственное замечание: если клиентский клиент решит обернуть ваш оператор CREATE TABLE в sp_executesql или в каком-то другом случае, временная таблица будетимеют вложенное время жизни пакета, а не время жизни сеанса.Но System.Data.SqlClient не сделает этого, если вы не поместите параметры в пакет, который создает временную таблицу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...