You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在EntityFramework.Core中解锁Sqlite数据库文件

问题说明

运行在net6.0上的项目使用Microsoft.EntityFrameworkCore.Sqlite 6.0.5版本时,预期DbContext释放后SQLite数据库文件会自动解除锁定,但实际观测到DbContext被释放、甚至终结器执行完成后,数据库文件仍处于锁定状态。
使用的DbContext代码如下:

public class MyContext : DbContext
{
    ~MyContext()
    {
        Console.WriteLine("Finaliser was called.");
    }

    public override void Dispose()
    {
        base.Dispose();
        Console.WriteLine("Dispose was called.");
    }

    public static readonly string DbFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "_temp.db");

    public DbSet<Foo> Summaries { get; set; }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.Entity<Foo>().HasKey(nameof(Foo.Id));
    }

    protected override void OnConfiguring(DbContextOptionsBuilder options)
    {
        options.UseSqlite($"Data Source={DbFile}");
    }
}

调用上下文的代码如下:

public static void AddItem()
{
    using var ctx = new MyContext();
    ctx.Database.EnsureCreated();
    ctx.Summaries.Add(new Foo {Bar = "Foo"});
    ctx.SaveChanges();        
}
问题原因

这个行为是Microsoft.Data.Sqlite默认的连接池机制设计导致的:DbContext释放时,关联的数据库连接不会直接关闭销毁,而是回到连接池中等待复用,因此数据库文件的句柄会一直被进程持有,锁不会随DbContext释放自动解除。

解决方案

根据业务场景二选一即可:

  • 方案1:全局禁用连接池
    在SQLite连接字符串中追加Pooling=False参数,关闭连接池能力,DbContext释放时会直接关闭底层连接,立即释放文件锁:
    protected override void OnConfiguring(DbContextOptionsBuilder options)
    {
        options.UseSqlite($"Data Source={DbFile};Pooling=False");
    }
    
    该方案适合数据库访问频次不高、不需要连接池提升性能的场景。
  • 方案2:按需手动清空连接池
    如果需要保留连接池的性能收益,不需要全局关闭池化,可以在需要释放文件锁的节点手动清空连接池:
    1. 首先引入对应命名空间:
      using Microsoft.Data.Sqlite;
      
    2. 确认所有相关DbContext都已经释放后,在操作数据库文件(删除、移动、备份等)之前调用静态方法:
      SqliteConnection.ClearAllPools();
      
    该方法会立即关闭连接池中所有空闲连接,释放所有持有的数据库文件锁,适合大部分业务场景保留性能、仅特殊节点释放锁的需求。
额外优化建议

当前代码中重写Dispose的写法不符合.NET的Dispose模式规范,会导致对象终结器必然被执行,产生不必要的性能开销,建议补充GC.SuppressFinalize调用:

public override void Dispose()
{
    base.Dispose();
    GC.SuppressFinalize(this);
    Console.WriteLine("Dispose was called.");
}

内容的提问来源于stack exchange,提问作者Sean Kearon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 12:33:08