使用 EntityFramework 6.1 抽真空 Sqlite 数据库

Jos*_*eph 4 .net c# sqlite entity-framework vacuum

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

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

在阅读了这篇优秀的博客SQLite、VACUUM 和 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;");
}
Run Code Online (Sandbox Code Playgroud)

我很惊讶收到以下异常:

附加信息: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)
Run Code Online (Sandbox Code Playgroud)

它让我认为 ExecuteSqlCommand 方法执行的所有命令都是在事务中处理的。我将EntityFramework 6.1.3 和System.Data.Sqlite 1.0.97.0 与 .NET Framework 4.5 一起使用。

问题

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

Ham*_*jam 8

试试这个来强制 EF 不使用事务,因为

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

context.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, "VACUUM;");
Run Code Online (Sandbox Code Playgroud)