当我尝试将Entity Framework Core与Sqlite一起使用且文件扩展名为.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,您将看到它有效。这意味着不存在文件的问题。
答案 0 :(得分:1)
问题是由于之前的连接仍然可以访问该文件。
正如下面的主题中提到的,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;");