当我尝试使用带有Sqlite的Entity Framework Core和.db
或.sqlite
的文件扩展名时,我收到错误
SqliteException:SQLite错误14:'无法打开数据库文件'
如果我删除文件扩展名,那么它工作正常。
我对Entity Framework Core不太熟悉,过去一直在使用像npoco这样的东西。我正在研究DataStorage和DataAggregator,我遇到了需要实现一些hackery的问题。我不喜欢它,它让我觉得很脏。
如果我从连接字符串中删除.db
,那么它工作正常,但如果我留下任何文件扩展名(我只尝试过.db
和.sqlite
),我得到了这个错误。
重新创建的步骤:
dotnet run
此解决方案(或使用单元测试)并在浏览器中转到AggregateResults ControllerAction。它将尝试查找以.db
结尾的所有文件以及_db_metadata.json
中的所有文件,并且将找不到并将返回“0”到浏览器页面。DataStorageService\DataStorageService\TransmittedFiles
存储库并清除它。去Endpoints\DataStorage\AggregateData\AggregateDataContext.cs
。注释掉这些线条
if (OperatingSystemHelpers.IsOSWindows)...
直到......为止
.Remove(connectionStringFileLocation.Length - 3);
尝试完成您之前所做的工作,您将看到1)AggregateData.db文件仍在TransmittedFiles中创建,2)您应该看到SqliteError 14。如果再次清除TransmittedFiles文件夹并重新使用OperatingSystemHelpers Clause,您将看到它有效。这意味着它不是文件不存在的问题。
该问题的结果来自之前的连接仍然可以访问该文件。
正如下面的主题中所提到的,Sqlite的C#实现有一个怪癖,在.Close()后,连接没有真正清理,直到垃圾收集运行
System.Data.SQLite Close() not releasing database file
要修复它,你可以将IDisposable添加到你的IAggregateDataRepository并实现类似下面的dispose方法:
public void Dispose()
{
_database.Dispose();
GC.Collect();
GC.WaitForPendingFinalizers();
}
您需要在测试中调用处理器,这可以通过在TearDown方法的顶部添加以下内容来完成:
if (_aggregateDataRepository != null)
{
_aggregateDataRepository.Dispose();
}
如果您在应用程序上下文构造函数的末尾添加此行,这将是一个额外的建议,它将确保您始终处于“Write Ahead Log”模式,这对多个连接更为满意。这不是修复问题所必需的,但是当你想在sqlite上创建一个安静的web api接口时,它将协助并发调用。
Database.ExecuteSqlCommand("PRAGMA journal_mode=WAL;");