Как я могу выполнить .sql из С#?

Для некоторых тестов интеграции я хочу подключиться к базе данных и запустить файл .sql, который имеет схему, необходимую для фактического запуска тестов, включая инструкции GO. Как я могу выполнить файл .sql? (или это совсем не тот путь?)

Я нашел сообщение в форуме MSDN, показывая этот код:

using System.Data.SqlClient;
using System.IO;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string sqlConnectionString = "Data Source=(local);Initial Catalog=AdventureWorks;Integrated Security=True";
            FileInfo file = new FileInfo("C:\\myscript.sql");
            string script = file.OpenText().ReadToEnd();
            SqlConnection conn = new SqlConnection(sqlConnectionString);
            Server server = new Server(new ServerConnection(conn));
            server.ConnectionContext.ExecuteNonQuery(script);
        }
    }
}

но в последней строке я получаю эту ошибку:

System.Reflection.TargetInvocationException: Исключение было вызвано цель вызова. --- > System.TypeInitializationException: Инициализатор типа для '' бросил исключение. --- > .ModuleLoadException: Модуль С++ не загружался во время Инициализация приложения. --- > System.DllNotFoundException: невозможно выполнить загрузить DLL 'MSVCR80.dll': указанный модуль не найден. (Исключение от HRESULT: 0x8007007E).

Мне сказали пойти и скачать эту DLL откуда-то, но это звучит очень хаки. Есть ли более чистый способ? Есть ли другой способ сделать это? Что я делаю неправильно?

Я делаю это с Visual Studio 2008, SQL Server 2008,.Net 3.5SP1 и С# 3.0.

Ответы

Ответ 1

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

Для выполнения запросов не требуется SMO. Вместо этого попробуйте использовать объект SqlCommand. Удалите их с помощью операторов. Используйте этот код для выполнения запроса:

 SqlConnection conn = new SqlConnection(sqlConnectionString);
 SqlCommand cmd = new SqlCommand(script, conn);
 cmd.ExecuteNonQuery();

Также удалите ссылку на проект для SMO. Примечание: вы захотите правильно очистить ресурсы.

Обновление:

Библиотеки ADO.NET не поддерживают ключевое слово 'GO'. Похоже, ваши варианты:

  • Разберите script. Удалите ключевые слова "GO" и разделите script на отдельные партии. Выполняйте каждую партию как свою собственную SqlCommand.
  • Отправьте script в SQLCMD в оболочке (ответ Дэвида Андреса).
  • Используйте SMO, как код из сообщения в блоге.

Собственно, в этом случае я думаю, что SMO может быть лучшим вариантом, но вам нужно будет выяснить, почему DLL не была найдена.

Ответ 2

MSVCR80 - это среда исполнения Visual С++ 2005. Возможно, вам потребуется установить пакет времени выполнения. Подробнее см. http://www.microsoft.com/downloads/details.aspx?FamilyID=200b2fd9-ae1a-4a14-984d-389c36f85647&displaylang=en.

В дополнение к разрешению проблемы с DLL и ответам Мэтта Брунелла (что я считаю более подходящим для того, что вы пытаетесь сделать), вы можете использовать инструмент командной строки SQLCMD (из установки инструментов SQL Client) для выполнения этих SQL-скрипты. Просто убедитесь, что это на вашем пути, чтобы вы не боролись с местами пути.

Это будет выглядеть так:

Фактическая команда:

SQLCMD -S myServer -D myDatabase -U myUser -P myPassword -i myfile.sql

Параметры (дело имеет значение):

S: server
d: database
U: User name, only necessary if you don't want to use Windows authentication
P: Password, only necessary if you don't want to use Windows authentication
i: File to run

Код для выполнения файлов SQL:

var startInfo = new ProcessStartInfo();
startInfo.FileName = "SQLCMD.EXE";
startInfo.Arguments = String.Format("-S {0} -d {1}, -U {2} -P {3} -i {4}",
                                    server,
                                    database,
                                    user,
                                    password,
                                    file);
Process.Start(startInfo);

Подробнее о инструменте SQLCMD см. http://msdn.microsoft.com/en-us/library/ms162773.aspx.

Ответ 3

При такой же необходимости автоматически запускать сгенерированную базу данных script из кода я решил разобрать SQL script, чтобы удалить инструкции GO и разделить script на отдельные команды (как это предложил @MattBrunell). Удаление инструкций GO было простым, но расщепление операторов на "\r\n" не сработало, так как это привнесло многострочные операторы. Испытывая несколько разных подходов, я был очень удивлен, узнав, что script не нужно разделить на отдельные команды. Я просто удалил все инструкции "GO" и отправил целое script (включая комментарии) в SqlCommand:

  using System.Data.SqlClient;

  using(SqlConnection connection = new SqlConnection(connectionString))
  using(SqlCommand command = connection.CreateCommand())
  {
    string script = File.ReadAllText("script.sql");
    command.CommandText = script.Replace("GO", "");
    connection.Open();
    int affectedRows = command.ExecuteNonQuery();
  }

Этот код был протестирован с SQL Server 2008 R2 и script, сгенерированный "База данных → Задачи → Сгенерировать скрипты...". Ниже приведены примеры команд в script:

USE [MyDatabase]

ALTER TABLE [MySchema].[MyTable] DROP CONSTRAINT [FK_MyTable_OtherTable]
DROP TABLE [MySchema].[MyTable]

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON

/****** Object:  Table [MySchema].[MyTable]    Script Date: 01/23/2013 13:39:29 ******/
CREATE TABLE [MySchema].[MyTable](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Subject] [nvarchar](50) NOT NULL,
    [Body] [nvarchar](max) NOT NULL,
 CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

SET IDENTITY_INSERT [MySchema].[MyTable] ON
INSERT [MySchema].[MyTable] ([Id], [Subject], [Body]) VALUES (1, N'MySubject', N'Line 1
Line 2
Line 3
Multi-line strings are also OK.
')
SET IDENTITY_INSERT [MySchema].[MyTable] OFF

Я предполагаю, что может быть некоторая максимальная длина для одного SqlCommand, над которым нужно разделить script. Мой script, который выполняется без проблем, содержит около 1800 операторов и составляет 520 кБ.

Ответ 4

Вы пытались запустить это с очень, очень простым script в файле .sql? Может быть, что-то, что просто вставляет одну строку или создает произвольную таблицу? Что-то, что очень легко проверить? По сути, этот код похож на жесткое кодирование sql, за исключением того, что вы читаете его из файла. Если вы можете заставить его работать с очень простым файлом, я бы сказал, что, вероятно, что-то не так с самой файловой структурой. Сообщение ссылалось на то, что есть некоторые положения относительно того, что может и не может быть в файле. Если ничего другого, это хорошее место для начала устранения неполадок.

Ответ 5

Вам может быть интересно: http://geekswithblogs.net/thomasweller/archive/2009/09/08/automating-database-script-execution.aspx

Он представляет собой универсальное "тестовое устройство" для автоматического выполнения sql-скриптов. Существует также пример кода, и нет никаких зависимостей от каких-либо необычных сборок...

Ответ 6

Если вы добавите следующие ссылки в свой проект, исходный код будет работать нормально.

Я использую SQL 2008 Express.

Путь: C:\Program Files (x86)\Microsoft SQL Server\100\SDK\Assemblies\

Файлы: microsoft.sqlserver.smo.dll, microsoft.sqlserver.connectioninfo.dll и Microsoft.SqlServer.Management.Sdk.Sfc.dll