使用EntityFramework 6.1实现真空Sqlite数据库

时间:2015-06-30 00:29:03

标签: c# .net entity-framework sqlite vacuum

最近作为娱乐,我决定开发一个小项目来测试SQlite与库System.Data.SQLite提供的EntityFramework的好处。

应用程序有一个数据同步过程,随着时间的推移已经过时,所以我决定从数据库中删除它们。正如预期的那样,通过删除表行不会减小数据库的大小,所以我决定在其中运行命令VACUUM。

在阅读了这篇优秀博客SQLite, VACUUM, and auto_vacuum之后,一切都变得更加清晰,特别是在命令无法在交易中执行的事实。

就像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方法执行的所有命令都在事务中处理。我在.NET Framework 4.5中使用EntityFramework 6.1.3和System.Data.Sqlite 1.0.97.0。

问题

我错了吗?如果是这样,有没有办法执行命令?

1 个答案:

答案 0 :(得分:4)

尝试此操作以强制EF不使用事务,因为

  

如果存在打开的交易,或者存在交易,则VACUUM将失败   运行时的一个或多个活动SQL语句。

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