5

最近、エンターテインメントとして、ライブラリSystem.Data.SQLiteによって提供される EntityFramework を使用して SQlite の利点をテストする小さなプロジェクトを開発することにしました。

アプリケーションにはデータ同期プロセスがあり、時間の経過とともに古くなるため、データベースから削除することにしました。予想通り、テーブルの行を削除してもデータベースのサイズは縮小されないので、そこで 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;");
}

次の例外を受け取って驚きました。

追加情報: 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 を使用しています。

質問

私はそれについて間違っていますか?もしそうなら、コマンドを実行する方法はありますか?

4

1 に答える 1

9

EFがトランザクションを使用しないようにするには、これを試してください。

開いているトランザクションがある場合、または実行時にアクティブな SQL ステートメントが 1 つ以上ある場合、VACUUM は失敗します。

context.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, "VACUUM;");
于 2015-06-30T00:34:40.923 に答える