Произошла ошибка при разборе запроса. Как это устранить?

#c# #parsing #sql-server-ce #executenonquery

#c# #синтаксический анализ #sql-server-ce #executenonquery

Вопрос:

Я хочу запустить инструкцию sql, которую я сначала прочитал из .sql файла.

Я получаю эту ошибку: {"There was an error parsing the query. [ Token line number = 13,Token line offset = 1,Token in error = ALTER ]"}

В .sql файле есть моя инструкция sql:

 CREATE TABLE [Test]
(
   [Id] INT NOT NULL IDENTITY (1,1),
   [DatabaseVersion] NVARCHAR(20) NOT NULL,
   [Autorun] BIT,
   [CurrentCulture] NVARCHAR(10),
   [MailNotificationEnabled] BIT,
   [RefreshInterval] INT,
   [ModifiedDate] DATETIME NOT NULL,
   [schemat] NVARCHAR(255)
)

ALTER TABLE [Test] ADD CONSTRAINT [PK_Test] PRIMARY KEY ([Id])

UPDATE [AppConfig]
SET [DatabaseVersion] = '0.12'
  

Чтение файла:

 string oldVersion = GetOldDatabaseVersion();
string sqlScript = "";
sqlScript = GetScriptFromAssembly(oldVersion, 
ConfigurationSettings.ValidDatabaseVersion);

ExecuteNonQuery(CommandType.Text, sqlScript);
  

ExecuteNonQuery метод:

 public int ExecuteNonQuery(CommandType type, string sql)
{
    using (SqlCeConnection connection = CreateConnection())
    {
        return ExecuteNonQuery(connection, type, sql);
    }
}

private int ExecuteNonQuery(SqlCeConnection connection, CommandType type, string sql)
{
    using (SqlCeCommand command = new SqlCeCommand())
    {
        command.Connection = connection;
        command.CommandType = type;
        command.CommandText = sql;

        return command.ExecuteNonQuery();
    }
}
  

Я не знаю, как это решить. Когда я запускаю скрипт непосредственно в db, он работает.

Комментарии:

1. Я бы предположил, что SqlCommand нужно, чтобы команда была разделена на ; ? Это всего лишь предположение, потому что, похоже, оно не распознает, что ALTER запускает новый оператор.

2. Я пробовал это ;/

3. Что я сейчас сделал — запускаю каждую инструкцию (create, alter и т.д.) Отдельно. Это работает. Но я не хочу создавать все инструкции в отдельных файлах ;/

Ответ №1:

Решена:

 string sqlScript = GetScriptFromAssembly(GetOldDatabaseVersion(), ConfigurationSettings.ValidDatabaseVersion);

string[] scripts = sqlScript.Split(new string[] { @"/*$$*/" }, StringSplitOptions.None);

foreach(var script in scripts)
    ExecuteNonQuery(CommandType.Text, script);
  

Добавлены разделители в sql:

 CREATE TABLE [Test]
(
   [Id] INT NOT NULL IDENTITY (1,1),
   [DatabaseVersion] NVARCHAR(20) NOT NULL,
   [Autorun] BIT,
   [CurrentCulture] NVARCHAR(10),
   [MailNotificationEnabled] BIT,
   [RefreshInterval] INT,
   [ModifiedDate] DATETIME NOT NULL,
   [schemat] NVARCHAR(255)
)

/*$$*/
ALTER TABLE [Test] ADD CONSTRAINT [PK_Test] PRIMARY KEY ([Id])

/*$$*/
UPDATE [AppConfig]
SET [DatabaseVersion] = '0.12'
  

Ответ №2:

Вы должны запускать каждый оператор как отдельную команду, вы можете использовать код, подобный вспомогательной функции, для разделения на команды, если вы разделяете каждую команду с помощью GO:

https://github.com/ErikEJ/SqlCeToolbox/blob/master/src/API/Repositories/ServerDBRepository.cs#L639

Как вы можете видеть, для этого я использую SqlCommandReaderStreamed из пакета DbUp

Ответ №3:

  • Пожалуйста, используйте ключевое слово Go перед изменением таблицы

Комментарии:

1. afaik GO это не SQL и просто используется такими инструментами, как sql management studio, для разделения пакетов. Но она не передается на сервер, поэтому она не должна быть частью текста команды SqlCommand .