EFCore を LocalDB (SQL Server Express) で動かした際、DB ファイルを消したいのにプロセスにロックされている場合

原因は、LocalDB のプロセスがファイルをアタッチしたままだから。これは、コード側で Dispose() しても GC してもダメ。呼び出し元のプロセスが落ちるまでは mdf ファイルは握られている。

単体テストを並列で走らせたりした際に困ることになる。

で、この問題は、利用し終わった際に、自分で自分をデタッチしてあげることで解決する。

例えば、単体テスト用のラッパー DbContext で、以下のように、生コンテキストを使って、自分をデタッチしてあげるだけ。

protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
var sql =
"declare @dbname varchar(max);"
+ "set @dbname = quotename(db_name());"
+ "exec('ALTER DATABASE ' + @dbname + ' SET OFFLINE WITH ROLLBACK IMMEDIATE;'); "
+ "exec('sp_detach_db ' + @dbname + ';'); ";
Context.Database.ExecuteSqlCommand(sql);
Context.Dispose();
}
disposedValue = true;
}
}

これで mdf ファイルはデタッチされ解放される。あとは、コードのなかで File.Delete() してもよし、ディレクトリ毎消してもよし。

President of team Sirocco, LLC / Financal Technology を中心に、技術界隈を実務もやりつつ見続けてます。

President of team Sirocco, LLC / Financal Technology を中心に、技術界隈を実務もやりつつ見続けてます。