Как я могу выполнить .sql из C #? - PullRequest
15 голосов
/ 20 сентября 2009

Для некоторых интеграционных тестов я хочу подключиться к базе данных и запустить файл .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: Модуль C ++ не удалось загрузить во время инициализация приложения. ---> System.DllNotFoundException: невозможно загрузить DLL 'MSVCR80.dll': указано модуль не найден (Исключение от HRESULT: 0x8007007E).

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

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

Ответы [ 6 ]

29 голосов
/ 20 сентября 2009
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 . Похоже, ваши варианты:

  1. Разобрать скрипт. Удалите ключевые слова «GO» и разбейте скрипт на отдельные партии. Выполнять каждый пакет как свой собственный SqlCommand.
  2. Отправьте скрипт в SQLCMD в оболочке (ответ Дэвида Андреса).
  3. Используйте SMO как код из поста в блоге.

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

9 голосов
/ 20 сентября 2009

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

В дополнение к решению проблемы DLL и ответа Мэтта Брунелла (что, я считаю, более подходит для того, что вы пытаетесь сделать), вы можете использовать инструмент командной строки SQLCMD (из установки инструментов клиента SQL) для выполнения этих 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);

См. http://msdn.microsoft.com/en-us/library/ms162773.aspx для получения дополнительной информации об инструменте SQLCMD.

2 голосов
/ 23 января 2013

Имея ту же необходимость автоматического запуска сгенерированного сценария базы данных из кода, я решил разобрать сценарий SQL, чтобы удалить операторы GO, и разделить сценарий на отдельные команды (как предложено @MattBrunell). Удалить операторы GO было легко, но разделить операторы на "\r\n" не получилось, так как это испортило многострочные операторы. Протестировав несколько разных подходов, я с удивлением обнаружил, что сценарий вообще не нужно разбивать на отдельные команды. Я просто удалил все операторы "GO" и отправил весь скрипт (включая комментарии) в 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 и сценарием, созданным с помощью «База данных -> Задачи -> Создать сценарии ...». Ниже приведены некоторые примеры команд в сценарии:

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, выше которой скрипт должен быть разбит. Мой скрипт, который выполняется без проблем, содержит около 1800 операторов и составляет 520 КБ.

0 голосов
/ 24 февраля 2010

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

Я использую 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

0 голосов
/ 20 сентября 2009

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

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

0 голосов
/ 20 сентября 2009

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

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