2015-06-30 13 views
3

Недавно как развлечение я решил разработать небольшой проект, чтобы проверить преимущества SQlite с EntityFramework, предоставляемые библиотекой System.Data.SQLite.Вакуумная база данных Sqlite с EntityFramework 6.1

Приложение имеет процесс синхронизации данных, который со временем устаревает, поэтому я решил удалить их из базы данных. Как и ожидалось, размер базы данных не уменьшается путем удаления строк таблицы, поэтому я решил запустить команду VACUUM.

После прочтения этого замечательного блога SQLite, VACUUM, and auto_vacuum все стало намного понятнее, особенно тот факт, что команда не может быть выполнена в рамках транзакции.

Like Code First пока недоступен, мне нужно создать таблицы в базе данных со сценариями, поэтому в том же месте я выполняю команду.

using (var context = new Context()) 
{ 
    context.Database.CreateIfNotExists(); 

    context.Database.ExecuteSqlCommand(
     "CREATE TABLE IF NOT EXISTS \"main\".\"OutgoingMessages\" (\"Id\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\"AccountId\" TEXT NOT NULL ON CONFLICT ROLLBACK,\"MessageId\" TEXT NOT NULL ON CONFLICT ROLLBACK,\"Date\" datetime NOT NULL ON CONFLICT ROLLBACK,\"Status\" INTEGER NOT NULL ON CONFLICT ROLLBACK,\"Content\" BLOB NOT NULL ON CONFLICT ROLLBACK,\"Size\" INTEGER NOT NULL ON CONFLICT ROLLBACK,\"Hash\" TEXT NOT NULL ON CONFLICT ROLLBACK,\"Comment\" TEXT);" + 
     "CREATE TABLE IF NOT EXISTS \"main\".\"IncomingMessages\" (\"Id\" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\"AccountId\" TEXT NOT NULL ON CONFLICT ROLLBACK,\"MessageId\" TEXT NOT NULL ON CONFLICT ROLLBACK,\"Date\" datetime NOT NULL,\"Status\" INTEGER NOT NULL,\"Comment\" TEXT);"); 

    context.Database.ExecuteSqlCommand("VACUUM;"); 
} 

Я был удивлен получить следующее исключение:

Дополнительной информации: логическую ошибку SQL или отсутствующую базу данных. Невозможно VACUUM из транзакции.

An exception of type 'System.Data.SQLite.SQLiteException' occurred in EntityFramework.dll but was not handled in user code 
at System.Data.SQLite.SQLite3.Reset(SQLiteStatement stmt) 
at System.Data.SQLite.SQLite3.Step(SQLiteStatement stmt) 
at System.Data.SQLite.SQLiteDataReader.NextResult() 
at System.Data.SQLite.SQLiteDataReader..ctor(SQLiteCommand cmd, CommandBehavior behave) 
at System.Data.SQLite.SQLiteCommand.ExecuteReader(CommandBehavior behavior) 
at System.Data.SQLite.SQLiteCommand.ExecuteNonQuery(CommandBehavior behavior) 
at System.Data.SQLite.SQLiteCommand.ExecuteNonQuery() 
at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<NonQuery>b__0(DbCommand t, DbCommandInterceptionContext`1 c) 

Что это заставляет меня думать, что все команды, выполняемые по методу ExecuteSqlCommand обрабатываются в рамках транзакции. Я использую EntityFramework 6.1.3 и System.Data.Sqlite 1.0.97.0 с .NET Framework 4.5.

ВОПРОСЫ

ли я неправильно об этом? Если да, есть ли способ выполнить команду?

ответ

4

Попробуйте это, чтобы заставить EF не использовать транзакции, потому что

вакуумном потерпит неудачу, если есть открытая транзакция, или, если есть заявления один или несколько активных SQL при запуске.

context.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, "VACUUM;"); 
+1

Теперь это работает !!!! – Joseph

Смежные вопросы