【问题标题】:Entity Framework Core connection managementEntity Framework Core 连接管理
【发布时间】:2018-03-24 16:12:09
【问题描述】:

在一个 asp.net 核心项目中,我需要一个加密的 SQLite 数据库。为此,我创建了自己的SqliteEncryptedConnection,它继承自Microsoft.Data.Sqlite.SqliteConnection,并在Open() 方法中设置了加密密钥(执行PRAGMA key = ...)

我有一个扩展方法,它通过创建连接并提供它来配置我的 EF 上下文。

    public static void UseEncryptedSqlite(this DbContextOptionsBuilder optionsBuilder, string connectionString, string password)
    {
        var connection = new SqliteEncryptedConnection(connectionString, password);
        connection.Open();
        optionsBuilder.UseSqlite(connection);
    }

我必须先打开连接,然后再交给EF,否则每次查询都会被EF自动打开和关闭,Open()方法现在相当昂贵。

我对这个解决方案的问题是我的连接从未被释放或关闭!

  1. 在Open中设置加密密钥是否正确?
  2. 有没有办法知道上下文何时被释放?还是将其配置为在释放连接后关闭并释放连接?
  3. 还有其他(更好的)方法来管理连接吗?

肮脏的解决方案是在 EF 上下文的 Dispose 方法中释放连接,但我真的不想释放注入但不属于上下文的依赖项。

【问题讨论】:

  • 如果我正确理解您的问题,它就是设计使然。 DbContextOptions 对象不会被释放,并且将被 EF Core DbContext 的所有实例重用,因为选项在初始化时传递给 DbContext。从 2.0 preview1 开始,甚至可以轮询 DbContext 实例以获取高性能场景,请参阅blog post
  • @Tseng 连接没有被重用。每次注入新的 DbContext 时都会调用此方法。 -> 每个网络请求 1 个。幸运的是,这些连接似乎被正确地垃圾收集了。所以,最后,我不知道如果在垃圾收集发生之前没有调用 dispose/close 是否有问题。
  • 您找到解决方案了吗?如果 EF Core 上下文接收到已打开的连接,我也有同样的问题。在我的情况下,我无法在选项对象中关闭它,因为我需要在分片环境中建立连接,这就是我从ShardMap 对象的OpenConnectionForKey 方法接收它的方式。
  • @AdrianPavel 我用 Brice Lambson 的回复回答了我的问题。在您的情况下,如果连接由单个上下文使用,则可以安全地将其放置在上下文 Dispose 方法中

标签: .net sqlite asp.net-core entity-framework-core


【解决方案1】:

我从 EF 核心团队工作的 Brice Lambson 那里得到了答案:

您正朝着正确的方向前进——打开的连接更少。记住, SQLite 连接本质上只是文件流,所以保留它们 打开更长的时间并不是真正的问题。

如果每个连接只有一个 DbContext 实例,则 即使已创建连接,DbContext 仍然可以拥有该连接 外部。只需在 DbContext.Dispose() 中处理连接即可。

如果这还不够,您可以尝试创建一个连接池。 管理生命周期可能会变得棘手。重要的是,一个 连接不会在创建它的线程之外使用。

使用 Cache=Shared(即Shared-Cache Mode)也可能有帮助 吞吐量。

【讨论】:

  • 我有类似的情况,通过添加受密码保护的 Sqlite 连接,我注意到一个严重的性能问题。你有同样的经历吗?如果是这样,你做了什么来解决它?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-06
  • 1970-01-01
  • 2021-10-02
  • 2018-05-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多