如何在 ASP.NET MVC Core 中获取瞬态 DbContext?

问题描述 投票:0回答:2

我在 Startup.cs 中有以下内容:

services.AddDbContext<MyDbContext>(options => options.UseSqlite(Configuration.GetConnectionString("Sqlite")));

现在,我想启动一个具有短暂生命周期的

MyDbContext
实例。这样做的原因是因为我在启动时填充缓存。那么我怎样才能获得一个由我负责处置自己的
MyDbContext
实例呢?我手头有一个
IServiceProvider

serviceProvider.GetRequiredService<MyDbContext>();

抛出一个异常,表明它超出了范围。

我理解为什么抛出异常,但我不确定解决它的最佳方法是什么。

c# asp.net-core dependency-injection entity-framework-core
2个回答
6
投票

您需要手动创建一个范围,如下所示:

using (var scope = serviceProvider.CreateScope())
{
    var scopedServices = scope.ServiceProvider; 
    scopedServices.GetRequiredService<MyDbContext>();

     ...
}

这将提供一个作用域 dbcontext,当您使用完它时,作用域闭包将自动处理它。在 Web 请求期间,每个请求都会自动创建一个范围,因此它会在请求结束时被释放。


0
投票
我不清楚 2018 年

joe-audette 的回答。 它依赖于

serviceProvider
,我不确定它来自哪里。同样在创建范围后,它会执行以下操作:

var scopedServices = scope.ServiceProvider;

...看起来它正在检索一个...ServiceProvider,这...是它开始的东西。? 这些都不清楚。

如果我正在使用 aspnet core 编写一个 Minimal API 应用程序,则没有环境

serviceProvider
对象。有一个 WebAppBuilder,从构建器中我可以获得一个类型为 WebApplication 的应用程序。

鉴于此,这对我有用。 (.NET 核心 8.0)

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<TodoDb>(opt => opt.UseInMemoryDatabase("TodoList"));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
...

var app = builder.Build();

...add all my methods here...

// initialize the in-memory DB just to start out
using (var scope = app.Services.CreateScope())
{
  var serviceProvider = scope.ServiceProvider;
  using (var db = new TodoDb(serviceProvider.GetRequiredService<DbContextOptions<TodoDb>>())) {
    var todo = new Todo("go grocery shopping");
    db.Todos.Add(todo);
    db.SaveChanges();
  }
}

// start listening
var port = Environment.GetEnvironmentVariable("PORT") ?? "8080";
var url = $"http://0.0.0.0:{port}";
app.Run(url);

这篇文章给了我关键的提示,创建一个范围并从范围中获取服务提供商。

我不得不说,这个话题有点难以理解。我发现的大多数提示都是部分的、迟钝的、部分错误的或过时的。

© www.soinside.com 2019 - 2024. All rights reserved.