gpt4 book ai didi

c# - 在内存中使用 SQLite 运行 EF Core - 未配置数据库提供程序

转载 作者:行者123 更新时间:2023-12-03 21:21:39 26 4
gpt4 key购买 nike

我正在使用带有 SQL 服务器的 EF Core 和用于 IOC 的 StructureMap 编写 ASP.Net Core Web API。
图书馆项目都是.NetStandard2.0而 API 和单元测试是 NetCoreApp2.0 .

对于单元测试,我正在运行 XUnit 并将 SQL Server 换成内存中的 SQLite 数据库,因为它提供了完整的参照完整性。
我仍然使用与我的主代码相同的 IOC 设置,但我传入了一个结构映射注册表列表,以允许我替换 SQLite 上下文工厂而不是 sql 工厂。

这是我的 DbContext 的精简版:

public class MyDbContext : DbContext
{
public MyDbContext(DbContextOptions options) : base(options)
{
}
}

这是我的测试设置代码:
public IServiceProvider ServiceProvider { get; set; }

public MyServiceTests()
{
var services = new ServiceCollection();
var dataRegistry = new Registry();

dataRegistry.For<IContextFactory<MyDbContext>>().Use<SqlLiteContextFactory>();

if (SqlLiteContextFactory.Connection == null)
{
SqlLiteContextFactory.Connection = new SqliteConnection("DataSource=:memory:");
SqlLiteContextFactory.Connection.Open();
}

services
.AddEntityFrameworkSqlite()
//This is only here as some posts suggested this was needed, StartUp.cs for production site does not have this and works fine.
.AddDbContext<MyDbContext>(options => options.UseSqlite(SqlLiteContextFactory.Connection));

var registries = new List<Registry>
{
dataRegistry,
new CommandQueryRegistry(),
new ServiceRegistry(),
new TransformRegistry()
};

ServiceProvider = DependencyInjection.TestSetup(services, registries);
}

IOC 初始化代码相当基本:
public static IServiceProvider TestSetup(IServiceCollection services, List<Registry> registries)
{
var container = new Container();

var registry = new Registry();
registries.ForEach(r => registry.IncludeRegistry(r));

container.Configure(config =>
{
config.AddRegistry(registry);
config.ForSingletonOf<IHttpContextAccessor>().Use<HttpContextAccessor>();
config.Populate(services);
});

var serviceProvider = container.GetInstance<IServiceProvider>();
return serviceProvider;
}

这是我的 SQLite 上下文工厂的上下文工厂代码,它和 SQL 的唯一区别是我有静态 Connection属性以确保在处理上下文后我不会丢失数据库。
public class SqlLiteContextFactory : IContextFactory<MyDbContext>
{
public static SqliteConnection Connection;

private DbContextOptions<MyDbContext> CreateOptions(bool trackChanges)
{
var builder = new DbContextOptionsBuilder<MyDbContext>();
var optionsBuilder = new DbContextOptionsBuilder<MyDbContext>();
optionsBuilder.UseSqlite(Connection);

if (!trackChanges)
{
builder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
}

return builder.Options;
}

private MyDbContext CreateDbContext(bool trackChanges)
{
if (Connection == null)
{
Connection = new SqliteConnection("DataSource=:memory:");
Connection.Open();
}

var context = new MyDbContext(CreateOptions(trackChanges));

//Always keep context as most recent version in tests
context.Database.Migrate();

return context;
}

public MyDbContext CreateNonTrackedContext()
{
return CreateDbContext(false);
}

public MyDbContext CreateDbContext()
{
return CreateDbContext(true);
}
}

问题

我的代码在运行站点时运行良好,SQL 上下文工厂创建上下文并运行 migrate 命令来创建数据库没有问题。
但是,当我尝试通过单元测试来测试我的任何服务时,上下文工厂在尝试运行 Migrate 时会崩溃。具有以下内容:
System.InvalidOperationException : No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext.
at Microsoft.EntityFrameworkCore.Internal.DbContextServices.Initialize(IServiceProvider scopedProvider, IDbContextOptions contextOptions, DbContext context)
at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.GetRelationalService[TService](IInfrastructure`1 databaseFacade)
at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.Migrate(DatabaseFacade databaseFacade)
at API.Test.Utilities.SqlLiteContextFactory.CreateDbContext(Boolean trackChanges) in API.Test\Utilities\SqLiteContextFactory.cs:line 37
at API.Test.Utilities.SqlLiteContextFactory.CreateDbContext() in API.Test\Utilities\SqLiteContextFactory.cs:line 49
at API.CommandQueries.Commands.MyCommand.AddOrUpdate(MyModel model) in \API.CommandQueries\Commands\MyCommand.cs:line 21
at API.Services.MyService.Save(Model model) in API.Services\MyService.cs:line 40
at API.Test.MyTests.CanAdd() in API.Test\MyServiceTests.cs:line 47

我已经尝试了我能找到的解决这个问题的所有解决方案。加入 .AddDbContext到服务集合。确保测试项目和上下文项目都引用了 EntityFrameworkCore , EntityFrameworkCore.RelationalEntityFrameworkCore.Sqlite .确保 SQLite 连接保持事件状态并确保测试设置使用 .AddEntityFrameworkSqlite()ServiceCollection .

我还尝试将 SQLite 换成 EF Core InMemory Db 与另一个上下文工厂,但由于完全相同的问题而失败。

之前有没有其他人看到过这个问题,或者我是否以某种方式使用 EF Core 使其与 SQLite 不兼容?

最佳答案

不久前我在这方面工作过。而且我相信您需要运行迁移并保持连接打开。您正在覆盖静态连接。另外,在您使用连接之前,我不确定它是否已创建。

关于c# - 在内存中使用 SQLite 运行 EF Core - 未配置数据库提供程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51195927/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com