Entity Framework Core 1.0的DbContext未与HTTP请求相关联。

4

我通过观看这个视频与Rowan Miller(链接在此:https://channel9.msdn.com/Series/Whats-New-with-ASPNET-5/06,22分钟处)了解到,在Startup.cs中配置Entity Framework Core(之前称为EF7)到一个ASP.NET Core 1.0应用程序(之前称为ASP.NET 5)的方式如下:

    public void ConfigureServices(IServiceCollection services)
    {
        //Entity Framework 7 scoped per request??
        services.AddEntityFramework()
            .AddSqlServer()
            .AddDbContext<MyDbContext>(options =>
            {
                options
                  .UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]);
            });

        //MVC 6
        services.AddMvc();
    }

这个DbContext将被限定在http请求的范围内,因此无论在整个http管道中(包括中间件或MVC)何时使用DbContext,我们都可以确定由DI容器注入的实例是相同的。

但问题在于它似乎并不起作用。在MVC的生命周期内,确实会注入相同的DbContext实例,但正如在这里所述:Entity Framework Core 1.0 unit of work with Asp.Net Core middleware or Mvc filter,我正在尝试插入以下中间件来实现某种集中式Commit/Rollback功能,以便在控制器执行结束后进行处理:

public class UnitOfWorkMiddleware
{
    private readonly RequestDelegate _next;
    private readonly MyDbContext _dbContext;
    private readonly ILogger _logger;

    public UnitOfWorkMiddleware(RequestDelegate next, MyDbContext dbContext, ILoggerFactory loggerFactory)
    {
        _next = next;
        _dbContext = dbContext;
        _logger = loggerFactory.CreateLogger<UnitOfWorkMiddleware>();
    }

    public async Task Invoke(HttpContext httpContext)
    {
        await _next.Invoke(httpContext);
        _logger.LogInformation("Saving changes for unit of work if everything went good");
        await _dbContext.SaveChangesAsync();
    }
}

这个中间件在管道中紧接着MVC6之前。

//inside Configure(IApplicationBuilder app) in Startup.cs
app.UseMiddleware<UnitOfWorkMiddleware>();
app.UseMvcWithDefaultRoute();

我的中间件中的DbContext实例与MVC生命周期中注入的实例不同

这是预期的吗?一个DbContext不应该被限定在一个http请求范围内吗?是否可能实现我想要的效果?

备选方案是使用MVC 6全局过滤器(如果我能找到如何执行此操作的文档)。我假设作为MVC 6框架的一部分,注入的DbContext实例将是相同的..

1个回答

4
经过更多的测试,我可以确认DbContext仅在MVC执行期间被限定在http请求范围内(可能是MVC负责处理DbContext的释放),因此管道中之前或之后的任何中间件都不会注入相同的DbContext实例。因此,我决定向MVC 6添加全局过滤器(因为过滤器是MVC框架的一部分),以便在操作执行前后访问相同的DbContext实例。如果有人对如何创建此全局过滤器感兴趣,请查看:Entity Framework Core 1.0 unit of work with Asp.Net Core middleware or Mvc filter

我认为你非常错误地滥用了DbContext。这些东西应该尽可能晚地创建,尽可能快地销毁。 - DavidG
DbContext是由DI容器在http请求范围内实例化的。我仍然依赖它来创建和销毁DbContext实例。如果我的存储库保存了DbContext更改,这个DbContext实例仍然不会被销毁,直到MVC将响应传递给管道中的下一个项目(因为默认情况下它是由DI容器管理的,如果我没有弄错的话)。我的方法有什么不同吗? 是的,DbContext会比不使用过滤器时提前实例化一点,但在相同的时间销毁,你不觉得吗? - diegosasw
此外,我不知道有什么其他方法可以以事务方式处理HTTP请求,而不需要在控制器执行后有一个集中的地方来确保一切都正常。在控制器中注入DbContext是一个不好的想法,但在一个集中的过滤器中似乎是一个更好的方法。有没有关于事务式方法的建议? - diegosasw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接