【问题标题】:SQLite with Entity Framework Core is slow带有 Entity Framework Core 的 SQLite 很慢
【发布时间】: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 可能不适合您的情况。

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


【解决方案1】:

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

【讨论】:

  • 虽然 EF 在处理 DbContext 时处理 DbConnection,但 EF 核心保留 DbConnection。我还阅读了一篇文章,说应该为每个转换处理 DbContext。
猜你喜欢
  • 2017-02-15
  • 2017-08-23
  • 2020-08-09
  • 1970-01-01
  • 2017-10-28
  • 1970-01-01
  • 2013-04-30
  • 2021-03-23
  • 2019-02-24
相关资源
最近更新 更多