Ошибка входа при использовании SMO ​​для создания сценария SQL с параметром ScriptData

Я пытаюсь экспортировать и импортировать схему базы данных и данные внутри. Для этого я использую SMO (объекты управления сервером), но хотя экспорт схемы работает нормально, установка ScriptData на true в параметрах сценария приведет к исключению.

Server server = new Server(new ServerConnection(sqlCon));
Database database = server.Databases["SpectroGrass"];
ScriptingOptions options = new ScriptingOptions();
options.ScriptSchema = true;
options.ScriptData = false;
options.ScriptDrops = false;

string scriptData = String.Join("\r\n", database.Tables[tableName].EnumScript(options).ToList());

Будет производить схему и работает.

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON

CREATE TABLE [SpectroGrassAdmin].[Treatment]
(
    [TRM_ID] [int] NOT NULL,
    [TRM_Name] [varchar](150) COLLATE Latin1_General_CI_AS NULL,
    [TRM_Crop] [varchar](50) COLLATE Latin1_General_CI_AS NOT NULL
) ON [PRIMARY]

Но используя опцию ScriptData...

options.ScriptSchema = false;
options.ScriptData = true;
options.ScriptDrops = false;

string scriptData = String.Join("\r\n", database.Tables[tableName].EnumScript(options).ToList());

сгенерирует исключение.

Ошибка входа для пользователя SpectroGrassAdmin.

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

Мне не хватает некоторых других параметров, чтобы иметь возможность создать скрипт для данных таблицы?


person Endauriel    schedule 10.01.2020    source источник
comment
не могли бы вы проверить настройку AutoDisconnectMode контекста подключения? ($server.ConnectionContext , $server.ConnectionContext.AutoDisconnectMode) и, возможно, изменить его на 1 (:никогда не отключаться?) Каково значение/формат sqlCon? Кроме того, установите значение true как для схемы скрипта, так и для данных.   -  person lptr    schedule 10.01.2020
comment
В этот ответ включена дополнительная информация: https://stackoverflow.com/questions/37003017/scriptingoptions-sql-smo-does-not-support-scripting-data   -  person Martin Cairney    schedule 13.01.2020
comment
@lptr Установка AutoDisconnectMode ничего не изменила. Строка подключения была создана с помощью класса SqlConnectionStringBuilder. Он содержит источник данных, начальный каталог, идентификатор пользователя, пароль и имеет встроенную безопасность, установленную на false, а также время ожидания соединения, установленное на 0. Использование схемы и данных по-прежнему заканчивается исключением. Использование всех 3 (схема, данные и удаление) приведет к созданию только оператора удаления без схемы и данных.   -  person Endauriel    schedule 13.01.2020
comment
@MartinCairney Я использую все ссылки в предоставленной вами ссылке и на всякий случай попробовал Scripter вместо ScriptingOptions, но результат тот же. Единственная разница в том, что я использую SQL Sevrer 2017 вместо 2014.   -  person Endauriel    schedule 13.01.2020


Ответы (1)


Постарайтесь максимально упростить его. Особенность smo в том, что по умолчанию он указывает/подключается к экземпляру sql по умолчанию.

Бывает ли так, что у вас есть экземпляр по умолчанию на машине, на которой вы запускаете свое приложение, и вы пытаетесь переключиться на другой экземпляр? (либо вторичный на вашем компьютере, либо удаленный экземпляр на другом компьютере).

Было принято следующее: из примера smo с использованием ServerConnection, что позволяет повторно использовать информацию о соединении.

//  https://docs.microsoft.com/en-us/sql/relational-databases/server-management-objects-smo/create-program/connecting-to-an-instance-of-sql-server?view=sql-server-ver15#connecting-to-an-instance-of-sql-server-by-using-sql-server-authentication-in-visual-c

//// compile with:   
// /r:Microsoft.SqlServer.Smo.dll  
// /r:Microsoft.SqlServer.ConnectionInfo.dll  
// /r:Microsoft.SqlServer.Management.Sdk.Sfc.dll   

using System;
using System.Linq;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;

namespace SMOConsoleApp
{
    class Program
    {
        static void Main()
        {

            // For remote connection, remote server name / ServerInstance needs to be specified  
            ServerConnection srvConn2 = new ServerConnection("machinename"/* <--default sql instance on machinename*/);  // or (@"machinename\sqlinstance") for named instances
            srvConn2.LoginSecure = false;
            srvConn2.Login = "sql_login_goes_here";
            srvConn2.Password = "password_goes_here";
            Server srv3 = new Server(srvConn2);

            Console.WriteLine("servername:{0} ---- version:{1}", srv3.Name, srv3.Information.Version);   // connection is established  
            Console.WriteLine(srv3.ConnectionContext); //check connection context

            ScriptingOptions scriptoptions = new ScriptingOptions();
            scriptoptions.ScriptSchema = true;
            scriptoptions.ScriptData = true;
            scriptoptions.ScriptDrops = false;

            Database mydb = srv3.Databases["master"];
            /*
                --execute this in ssms, in the master db
                select *
                into dbo.testsysobjects
                from sys.objects
            */
            Table mytable = mydb.Tables["testsysobjects", "dbo"];

            Console.WriteLine("database: {0} ---- table: {1} ---- rowcount: {2}", mytable.Parent.Name, mytable.Name, mytable.RowCount); //check table

            string scriptData = String.Join("\r\n", mytable.EnumScript(scriptoptions).ToList());

            Console.Write(scriptData);

            srvConn2.Disconnect();

        }
    }
}
person lptr    schedule 13.01.2020
comment
Спасибо, это сработало, хотя я не знаю, почему. Я действительно использую другой экземпляр sql, но я предоставил его в SqlConnectionString, который я передал объекту ServerConnection. Должно быть, он не установил его должным образом или что-то в этом роде. Предоставление учетных данных для входа непосредственно в объект ServerConnection сработало. Я все еще не понимаю, почему все, что пошло не так, позволило мне экспортировать схему, но привело к неудачной попытке входа в систему при попытке экспортировать данные. - person Endauriel; 14.01.2020
comment
smo обрабатывает соединения, если объект serverconnection не определен явно. Даже в коде ответа Disconnect() не нужен (если ранее не использовался явный Connect()). Для экспорта схемы и данных smo открывает два разных соединения. То же самое происходит, когда ScriptDrops = true : 2 соединения, хотя возвращается только один оператор удаления. Можно предположить, что одно соединение предназначено для схемы, а другое — для данных. Обратите внимание, что соединения открываются/закрываются несколько раз (в первый раз не в пул, а затем в пул). - person lptr; 14.01.2020
comment
Может ли быть так, что первое соединение (о схеме) использует SqlConnectionStringBuilder, а второе соединение является еще одним экземпляром server(), который инициируется без строки соединения. Сервер() без определенного соединения подключается к экземпляру машины по умолчанию. Вы можете проверить это в своем коде, попробовав/поймав ScriptData и напечатав server.ConnectionContext в улове, чтобы проверить, к чему пытается подключиться экземпляр sql server(). - person lptr; 14.01.2020