【问题标题】:EF Core, Sqlite, InMemory, Code First - just HOW?EF Core、Sqlite、InMemory、代码优先——如何?
【发布时间】:2021-01-08 17:59:50
【问题描述】:

我想根据我的测试模型创建一个具有结构的数据库。 在记忆中。使用 Sqlite 和实体框架核心。 当然,代码优先。 我创建了我的模型。

Data\DataContext.cs:

using Microsoft.EntityFrameworkCore;

namespace MyTest.Data {

    public class DataContext : DbContext {

        public DbSet<Record> Records { get; set; }

        public DataContext(DbContextOptions options) : base(options) { }

    }

}

Data\Record.cs:

using System;

namespace MyTest.Data {

    public class Record {

        public int Id { get; set; }

        public string Name { get; set; }

        public string Description { get; set; }

        public DateTime Time { get; set; }

    }
}

我有这个测试代码:

using System;
using System.Data.Common;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;

using MyTest.Data;

namespace MyTest {
    
    public class Startup {
        
        static DbConnection TestDbConnection = new SqliteConnection("Data Source=:memory:;Cache=shared");

        void InitializeTestDatabase() {
            var dbOptions = new DbContextOptionsBuilder().UseSqlite(TestDbConnection).Options;
            var dbContext = new DataContext(dbOptions);
            dbContext.Database.EnsureCreated();
            for (int i = 0; i < 1024; i++) {
                var testString = Guid.NewGuid().ToString();
                dbContext.Records.Add(new Record { Name = testString.Substring(0, 8), Description = testString, Time = DateTime.Now });
            }
            dbContext.SaveChanges();
        }

    }

}

当然会抛出 SQL 异常,因为没有像“记录”这样的表。明显地。该结构通常是使用迁移创建的,但我读过您不能将迁移与InMemory 一起使用。我应该改用EnsureCreated()。但是,我怎样才能从我的模型代码中构建结构呢?我在这里错过了什么?

【问题讨论】:

  • 为什么需要使用 InMemory? in-mem 不应该是一个持久的数据库,因此使用迁移是没有意义的,迁移是一种随着时间的推移以理智和时间可滚动的方式发展生产数据库的设备。我相信 EnsureCreated 应该创建一个与模型兼容的数据库,并且(因为它也不会创建一个迁移功能的数据库)与 in-mem 的目标一致,但我不确定 in-mem 是什么你最终会想要做的。因此,您也许应该考虑使用迁移在磁盘上正常创建一个数据库(设计时间比运行时间多)
  • @CaiusJard 我只想创建一个测试表。用于测试的虚拟数据库中的虚拟表,但我想让它尽可能简单(零配置/依赖项/路径/文件引用)。另外,Code First - 所以我不想编写 SQL 或创建数据库结构 - EF 可以为我做到这一点,不是吗?我只关心有一个包含数据的表格。每次应用启动时创建。我不想要文件,我不想手动创建表格。

标签: c# sqlite entity-framework-core


【解决方案1】:

我需要在我的连接上添加SqliteConnection.Open 调用以使其正常工作:

var conn = new SqliteConnection("DataSource=:memory:");
conn.Open(); // open connection to use

var options = new DbContextOptionsBuilder<VegaDbContext>()
   .UseSqlite(conn)
   .Options;

using (var ctx = new VegaDbContext(options))
{
    ctx.Database.EnsureCreated();
    ctx.Records.ToList();
}

【讨论】:

  • 太棒了,当时我收到的错误消息具有误导性。它说我没有表Records,但是在我的数据上下文中使用它之前打开连接解决了这个问题。我对这个想法持怀疑态度,但我测试了它,它确实有效。非常感谢!
  • @Harry 很乐意提供帮助!我有同一张桌子和同样的问题)
  • 它已记录在案,只是有人必须阅读它 - Using SQLite in-memory databases
  • @IvanStoev 我先读了它,但无论如何我都忘了打开连接。我的错。那里发生了什么? EnsureCreated() 是否在打开连接时创建数据库结构并在关闭时静默跳过该结构?我只是好奇。
  • EnsureCreated 依赖于两个抽象方法bool Exists()bool HasTables()。它们由每个数据库提供者实现。 Sqlite 实现在名为 SqliteDatabaseCreator 的类中,您可以在 EF Core GitHub 存储库中找到它。 Exists 方法以 if (connectionStringBuilder.DataSource.Equals(":memory:", StringComparison.OrdinalIgnoreCase) || connectionStringBuilder.Mode == SqliteOpenMode.Memory) return true; 开头 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-23
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 2018-08-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多