Как я могу выполнить .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