带有 Entity Framework Core 的 SQLite 很慢

Posted

技术标签:

【中文标题】带有 Entity Framework Core 的 SQLite 很慢【英文标题】:SQLite with Entity Framework Core is slow 【发布时间】:2021-12-02 06:03:23 【问题描述】:

在 .NET Core 中通过 C# 中的 Entity Framework Core 向 SQLite DB 插入记录非常慢。它比我的预期慢 10 倍。有没有提高性能的魔法?

public class MyRecord

    [Key]
    public int ID  get; set; 
    public int Value  get; set; 


public class MyDatabase : DbContext

    public DbSet<MyRecord> Records  get; set; 

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    
        optionsBuilder.UseSqlite("Data source=mydb.db");
#if DEBUG
        optionsBuilder.EnableSensitiveDataLogging(true);
#endif
    


public class MyDatabaseTests

    public MyDatabaseTests()
    
        var db = new MyDatabase();
        db.Database.EnsureDeleted();
        db.Database.EnsureCreated();
    

    [TestMethod]
    public void EntityFramework1000Transactions()
    
        for (int i = 0; i < 1000; i++)
        
            using var db = new MyDatabase();
            var rec = new MyRecord
            
                ID = i+1,
                Value = 123456789
            ;
            var tx = db.Database.BeginTransaction();
            db.Records.Add(rec);
            db.SaveChanges();
            tx.Commit();
        
    

EntityFramework1000Transactions 在我的带有 SATA-SSD 驱动器的 PC 上需要 10 秒。替换为 eNVM 不是我的选择,因为我正在为一种具有等效存储的嵌入式系统编写应用程序。

我尝试使用db.ChangeTracker.AutoDetectChangesEnabled = false;,或者 db.BulkSaveChanges();(使用 Z.EntityFramework.Extensions.EFCore)

他们没有帮助我。

我的环境:

Visual Studio 2019 版本 16.11.2 .NET Core 3.1 C# Microsoft.EntityFrameworkCore.Sqlite 5.0.11 Windows 10

编辑

循环是应用程序中进程的模拟。它们不是单一的交易。 该循环旨在模拟 1000 笔交易。因此它们不能在同一个交易中。

它也不能删除事务。应用程序中的事务实际上更复杂,可以同时更新两个或多个表/记录。它必须在事务中处理。因此删除交易不是我的选择。

【问题讨论】:

一次添加所有记录,而不是循环。此外,无论您为每次迭代构建MyDatabase 的任何原因,都没有必要这样做。我认为解决这两个问题将大大提高性能。 重用上下文,删除事务并批量保存,而不是每个单独的项目。这不是魔法,只是正确使用了 EF Core 因此,您可能必须生成线程,而不仅仅是同步循环。我不相信在实际应用程序中你有 1000 个线程来完成这样的任务。此外,您不必启动事务,如果 SaveChanges 无法在一个 SQL 语句中执行,它会在后台执行此操作。 谢谢斯维亚托斯拉夫。我们的设备很少有线程并且可以相互通信。每个线程都有状态机,并且必须对电源循环安全。我最初调用单个 SaveChanges,但我了解到 DbContext 在调用 ExecuteSqlRaw 时会混淆。我还了解到,即使只更新一条记录,创建事务总是比没有事务快。 很难说该怎么做。 EF 增加了额外的开销,但我认为在这种情况下并不重要。无论如何测试没有 EF,只是通过 SQLiteConnection 和事务的纯 SQL。并且 SQLite 可能不适合您的情况。 【参考方案1】:

限制对数据库的连接命中数(在for循环内)可以解决this线程中提到的问题。

【讨论】:

虽然 EF 在处理 DbContext 时处理 DbConnection,但 EF 核心保留 DbConnection。我还阅读了一篇文章,说应该为每个转换处理 DbContext。

以上是关于带有 Entity Framework Core 的 SQLite 很慢的主要内容,如果未能解决你的问题,请参考以下文章

在 Entity Framework Core 中为 PostgreSQL 表的计算列设置公式

在 ASP.NET Core 中使用 Entity Framework 6

.NET Core 的 NUnit Entity Framework 集成测试依赖注入问题

Entity Framework Core Linq NULL 不起作用的地方

为啥运行时表达式会导致 Entity Framework Core 5 的缓存发生冲突?

在 Entity Framework Core 中查询系统版本时态表中的数据