为什么我不能在Entity Framework Core Sqlite文件中使用文件扩展名?

时间:2018-05-26 15:06:54

标签: c# entity-framework sqlite .net-core entity-framework-core

当我尝试将Entity Framework Core与Sqlite一起使用且文件扩展名为.db.sqlite时,出现错误

  

SqliteException:SQLite错误14:'无法打开数据库文件'

如果我删除了文件扩展名,那么它可以正常工作。

我对Entity Framework Core不太熟悉,并且过去一直在使用像npoco这样的东西。我正在研究DataStorage和DataAggregator,而且我遇到了需要实现一些hackery的问题。我不喜欢它,这让我觉得很脏。

如果我从连接字符串中删除.db,那么它可以正常工作,但如果我保留任何文件扩展名(我只尝试了.db.sqlite ),我得到了那个错误。

重新创建的步骤:

  1. 克隆https://github.com/EdLichtman/DataStorageService

  2. dotnet run此解决方案(或使用单元测试)并转到浏览器中的AggregateResults ControllerAction。它将尝试查找以.db结尾的所有文件以及_db_metadata.json中结尾的所有文件,并且将找不到任何文件,并将返回" 0"到浏览器页面。

  3. 现在转到DataStorageService\DataStorageService\TransmittedFiles存储库并清除它。去 Endpoints\DataStorage\AggregateData\AggregateDataContext.cs。注释掉

    if (OperatingSystemHelpers.IsOSWindows)...
    

    直到

    .Remove(connectionStringFileLocation.Length - 3);
    

    尝试完成您之前所做的工作,您将看到1)AggregateData.db文件仍在TransmittedFiles中创建,2)您应该看到SqliteError 14.

  4. 如果再次清除TransmittedFiles文件夹并重新使用OperatingSystemHelpers Clause,您将看到它有效。这意味着不存在文件的问题。

1 个答案:

答案 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;");

更多细节 https://www.sqlite.org/wal.html