未创建 EntityFrameworkCore SQLite 内存数据库表

     2023-02-16     282

关键词:

【中文标题】未创建 EntityFrameworkCore SQLite 内存数据库表【英文标题】:EntityFrameworkCore SQLite in-memory db tables are not created 【发布时间】:2019-10-12 15:36:02 【问题描述】:

对于集成测试,我正在使用 EntityFrameworkCore SQLite 内存数据库并根据 Microsoft 文档创建其架构,但是当我尝试播种数据时会引发异常,即表不存在。

DbContext.Database.EnsureCreated(); 的鼠标悬停文档:

确保上下文的数据库存在。如果存在,没有 采取行动。如果它不存在,那么数据库及其所有 架构被创建。如果数据库存在,则不执行任何操作 确保它与此上下文的模型兼容。

我读过EntityFrameworkCore 内存数据库仅在打开连接存在时才存在,因此我尝试显式创建var connection = new SqliteConnection("DataSource=:memory:"); 实例并将以下代码包装在using(connection) 块中并传递连接实例options.UseSqlite(connection);,但DbContext.Database.EnsureCreated(); 仍然没有创建任何数据库对象

public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<Startup>

    protected override IWebHostBuilder CreateWebHostBuilder()
    
        return WebHost.CreateDefaultBuilder()
            .UseStartup<Startup>();
    

    protected override void ConfigureWebHost(IWebHostBuilder builder)
    
      using (var connection = new SqliteConnection("DataSource=MySharedInMemoryDb;mode=memory;cache=shared"))
      
          connection.Open();
          builder.ConfigureServices(services =>
          
              var serviceProvider = new ServiceCollection()
                  .AddEntityFrameworkSqlite()
                  .BuildServiceProvider();

              services.AddDbContext<MyDbContext>(options =>
              
                  options.UseSqlite(connection);
                  options.UseInternalServiceProvider(serviceProvider);
              );

              var contextServiceProvider = services.BuildServiceProvider();

              // we need a scope to obtain a reference to the database contexts
              using (var scope = contextServiceProvider.CreateScope())
              
                  var scopedProvider = scope.ServiceProvider;

                  var logger = scopedProvider.GetRequiredService<ILogger<CustomWebApplicationFactory<TStartup>>>();

                  using (var myDb = scopedProvider.GetRequiredService<MyDbContext>())
                  
                      // DEBUG CODE
                      // this returns script to create db objects as expected
                      // proving that MyDbContext is setup correctly
                      var script = myDb.Database.GenerateCreateScript();
                      // DEBUG CODE

                      // this does not create the db objects ( tables etc )
                      // this is not as expected and contrary to ms docs
                      var result = myDb.Database.EnsureCreated();

                      try
                      
                          SeedData.PopulateTestData(myDb);
                      
                      catch (Exception e)
                      
                          // exception is thrown that tables don't exist
                          logger.LogError(e, $"SeedData.PopulateTestData(myDb) threw exception=[e.Message]");
                      
                  
              
          );
        
        builder.UseContentRoot(".");
        base.ConfigureWebHost(builder);
    

请注意,在这篇文章中,我只是在问为什么DbContext.Database.EnsureCreated(); 没有按预期创建架构。我没有将上述代码作为运行集成测试的一般模式。

【问题讨论】:

什么是chatDb?应该是MyDb 糟糕,现在已修复。 EF Core 内存数据库(与 SQLite 内存数据库相反)没有您描述的行为。你能指出我在哪里找到这个文件以便我修复它吗?谢谢。 【参考方案1】:

使用非共享 SQLite 内存数据库

SQLite 内存数据库默认是瞬态的。作为documentation states:

数据库连接一关闭,数据库就不再存在。每个 :memory: 数据库都彼此不同。

另一方面,EF Core 的 DbContext 始终自动打开和关闭与数据库的连接,除非您传递已经打开的连接。

因此,为了在 EF Core 中跨多个调用使用相同的 SQLite 内存数据库,您需要分别创建一个 SqliteConnection 对象,然后将其传递给每个 DbContext

例如:

  var keepAliveConnection = new SqliteConnection("DataSource=:memory:");
  keepAliveConnection.Open();

  services.AddDbContext<MyContext>(options =>
  
    options.UseSqlite(keepAliveConnection);
  );

请注意,SqliteConnection 并不是真正的线程安全的,因此这种方法仅适用于单线程场景。任何时候您希望拥有一个可以被多个线程访问的共享数据库(例如,在 ASP.NET Core 应用程序中,为多个请求提供服务),您都应该考虑使用磁盘数据库。

顺便说一下,这是EF Core documentation on how to use SQLite in-memory databases for testing目前使用的方法。

使用共享的 SQLite 内存数据库

SQLite 还支持命名shared in-memory databases。通过使用相同的连接字符串,多个SqliteConnection 对象可以连接到同一个数据库。然而:

当与数据库的最后一个连接关闭时,数据库会自动删除并回收内存。

因此,仍然需要维护一个单独的打开连接对象,以便数据库可以跨多个 EF Core 调用使用。例如:

  var connectionString = "DataSource=myshareddb;mode=memory;cache=shared";
  var keepAliveConnection = new SqliteConnection(connectionString);
  keepAliveConnection.Open();

  services.AddDbContext<MyContext>(options =>
  
    options.UseSqlite(connectionString);
  );

请注意,此方法不限于单个线程,因为每个 DbContext 都有自己的 SqliteConnection 实例。

【讨论】:

为什么DbContext.Database.EnsureCreated(); 会涉及“在 EF Core 中的多个调用中(使用)相同的 SQLite 内存数据库”?无论如何(正如我在帖子中指出的那样),我已经尝试显式创建一个 var connection = new SqliteConnection("DataSource=:memory:"); 实例并将我的代码包装在一个 using 块中并传递连接实例 options.UseSqlite(connection); ,但 DbContext.Database.EnsureCreated(); 仍然没有t 创建任何数据库对象。 DbContext.Database.EnsureCreated();DatabaseFacade 上的一个框架方法,我希望它只对内存中的SQLite 实例进行一次调用,以执行与@ 返回的脚本相同的创建脚本987654341@ 我确实仔细阅读了您的问题。我的这部分答案适用于所有找到此答案的人,因为他们正在尝试做与您类似的事情(但不完全相同)。使用 SQLite 内存数据库有一个值得指出的特定缺陷。 你的主旨完全是人为的。我的代码在 CustomWebApplicationFactory 的上下文中,这是模拟 Web 应用程序以进行集成测试所必需的。 请注意,Mode=Memory 不适用于 2.1,但已在 3.1 中修复。我得到它使用这个连接字符串"DataSource=file::memory:?cache=shared"

如何清除 dotnet-ef 错误文件未找到 <project>EntityFrameworkCore.targets

】如何清除dotnet-ef错误文件未找到<project>EntityFrameworkCore.targets【英文标题】:Howtocleardotnet-eferrorfilenotfound<project>EntityFrameworkCore.targets【发布时间】:2022-01-0804:04:30【问题描述】:我已使用EntityFramework6.0.0将ASP.NETCoreEnti 查看详情

EntityFrameworkCore - 将新列添加到联接表

】EntityFrameworkCore-将新列添加到联接表【英文标题】:EntityFrameworkCore-AddnewColumntoJointable【发布时间】:2021-12-1315:00:51【问题描述】:我有两个实体:publicclassBlogpubliclongIdget;set;publicstringContentget;set;publicICollection<Post>Postsget;s 查看详情

Microsoft.EntityFrameworkCore.Tools - 使用 .NET 5(隔离)设计时使用 HostBuilder 创建 DbContext 的 Azure Functions

】Microsoft.EntityFrameworkCore.Tools-使用.NET5(隔离)设计时使用HostBuilder创建DbContext的AzureFunctions【英文标题】:Microsoft.EntityFrameworkCore.Tools-AzureFunctionswith.NET5(Isolated)Design-timeDbContextCreationwithHostBuilder【发布时间】:2021 查看详情

张高兴的entityframeworkcore即学即用:创建第一个efcore应用(代码片段)

写在前面EntityFrameworkCore(EFCore)是.NET平台流行的对象关系映射(ORM)框架。虽然.NET平台中ORM框架有很多,比如Dapper、NHibernate、PetaPoco等,并且EFCore的性能也不是最优的(这是由于EF的实体跟踪特性,将其禁用后可以大幅提升性能... 查看详情

实体框架核心 DbContextFactory 未注册

】实体框架核心DbContextFactory未注册【英文标题】:EntityFrameworkCoreDbContextFactorynotregistering【发布时间】:2021-12-2715:24:36【问题描述】:我正在使用.NET5和EntityFrameworkCore以及HotChocolate来创建GraphQLapi。列出的为从api获得适当性能的必... 查看详情

MySql EntityFrameworkCore System.TypeLoadException

】MySqlEntityFrameworkCoreSystem.TypeLoadException【英文标题】:【发布时间】:2018-01-0810:23:15【问题描述】:我正在尝试使用以下代码将我的WebAPI连接到MySql数据库:publicclassStartuppublicvoidConfigureServices(IServiceCollectionservices)stringconn_string="se... 查看详情

如何使用 EntityFrameworkCore 定义父/子关系?

】如何使用EntityFrameworkCore定义父/子关系?【英文标题】:Howtodefineparent/childrenrelationwithEntityFrameworkCore?【发布时间】:2021-12-1202:42:12【问题描述】:我有一个项目使用EntityFrameworkCore来访问数据库中的数据。我正在尝试为单个对... 查看详情

aspnetcore2.0中entityframeworkcore及autofac的使用(附demo)((代码片段)

一,通过Entityframeworkcore中DbFirst模式创建模型这里只说一下Entityframeworkcore中DbFirst模式创建模型,想了解CodeFirst的可以自行度娘,还是在原有项目中创建一个Model类库,然后通过通过vs中NuGet的程序包管理控制台执行 安装EntityFr... 查看详情

我应该将啥 DbContext 与 EntityFrameworkCore 一起使用?

】我应该将啥DbContext与EntityFrameworkCore一起使用?【英文标题】:WhatDbContextshouldIusewithEnityFrameworkCore?我应该将什么DbContext与EntityFrameworkCore一起使用?【发布时间】:2019-04-1205:45:39【问题描述】:我有带有EFCore的.NetCore应用程序。... 查看详情

第15章使用entityframeworkcore进行配置和操作数据i(代码片段)

...存储机制。本快速入门展示了如何配置IdentityServer以使用EntityFrameworkCore(EF)作为此数据的存储机制(而不是使用我们迄今为止使用的内存中实现)。注意除了手动配置EF支持外,还有一个IdentityServer模板可用于创建具有EF支持的... 查看详情

s-s-rS 报告管理器未正确显示

...4:20:15【问题描述】:我是ReportingServices的新手,最近开始创建报告。我正在使用MSSQLServer随附的BIDS中创建报告,出于我的目的,R2,并已配置报告服务器强>也。一切安好。我可以使用BIDS预览报告、调试、部署等等。但是,问... 查看详情

System.TypeLoadException:“MySql.Data.EntityFrameworkCore.Query.Internal.MySQLSqlTranslatingExpressio

】System.TypeLoadException:“MySql.Data.EntityFrameworkCore.Query.Internal.MySQLSqlTranslatingExpressionVisitorFactory”类型中的方法“创建”【英文标题】:System.TypeLoadException:Method\'Create\'intype\'MySql.Data.EntityFrameworkCore.Query. 查看详情

s-s-rS 未显示日期范围内的所有数据

...间】:2021-08-3019:45:30【问题描述】:您好,我正在使用SQL创建一个报告,显示日期范围之间的tranx信息。但是我有一个有趣的问题,我会用下表来说明它PressStatusDateABStart08/01/2021ABQACheck08/02/2021ABDown08/02/202 查看详情

s-s-rS 2005 的报表管理器未打开

...理器时遇到问题。在IIS上分别为报表服务器和报表管理器创建名为ReportServer和Reports的虚拟目录。但是在IIS中浏览ReportServer目录时,出现错误提示:\'Aninte 查看详情

s-s-rS 报告未在 ASP.NET 网站中呈现

...ite【发布时间】:2015-02-2714:54:12【问题描述】:我们已经创建了一些s-s-rS报告,这些报告又可以使用ReportViewer控件在ASP.NET页面中提供。报告的呈现时间从8分钟到15分钟不等(一份巨大的报告)。注意:报告没有分组或重格式。... 查看详情

关于对entityframeworkcore3.1的理解与总结(代码片段)

EntityFrameworkCore是一个ORM,所谓ORM也是ef的一个框架之一吧,简单的说就是把C#一个类,映射到数据库的一个表,把类里面的属性映射到表中的字段。然后EntityFrameworkCore3.1是一个长期支持的版本。本人非常乐意对.NET社区繁荣奉献... 查看详情

ef.core读取数据库创建实体类

...序2.打开程序包管理器控制台3.输入:Install-PackageMicrosoft.EntityFrameworkCore.Tools4.输入:Install-PackageMicrosoft.EntityFrameworkCore.Sqlite5.输入:Scaffold-DbContext\'DataSource=D:\\kfdata.db;\'Microsoft.EntityFrameworkCore.Sqlite  -OutputDirModels 完成后... 查看详情

带有 EntityFrameworkCore 的 ASP.NET Core 中的 SQLite

】带有EntityFrameworkCore的ASP.NETCore中的SQLite【英文标题】:SQLiteinASP.NETCorewithEntityFrameworkCore【发布时间】:2016-07-2901:25:59【问题描述】:如何使用EntityFramework7在ASP.NETCoreWeb应用程序中添加和使用SQLite数据库?当我听说ASP.NETCore并创... 查看详情