在使用 Autofac 管理范围的每个请求后正确调用 EF SaveChanges
properly call EF SaveChanges after each request with Autofac managing scope
我想在每个请求结束时为我的项目 SaveChanges
添加一些基础设施到我的数据库上下文中。
所以我创建了一个简单的 Owin 中间件
app.Use(async (ctx, req) => {
await req();
var db = DependencyResolver.Current.GetService<MyDbContext>();
await db.SaveChangesAsync();
});
这不起作用并抛出错误
Instances cannot be resolved and nested lifetimes cannot be created from this LifetimeScope as it has already been disposed.
如果我在完成请求之前解析数据库
app.Use(async (ctx, req) => {
var db = DependencyResolver.Current.GetService<MyDbContext>();
await req();
await db.SaveChangesAsync();
});
它不会抛出错误,但它也不起作用(因为更改未保存到数据库中,在调试器中查看数据库显示 DbSet
的 Local
属性 抛出一个关于它被处理的 InvalidOperationException
。
我试过使用和不使用异步,在 autofac 配置之前和之后注册中间件 (app.UseAutofacMiddleware(container)
) 并直接从 Owin 环境解析 LifetimeScope
。都给我相同的结果。
我以前用 Structuremap 做过类似的事情,但似乎无法找到让 Autofac 正常运行的正确方法。
史蒂文关于您不应该提交请求处理这一事实是正确的,因为您无法确定您是否真的想在那里提交,除非您从 DbContext 中抽象出您的 UoW 并在那里保留一个成功属性,检查是否关于处置和有条件地提交。
对于您的具体问题,有两点需要澄清。
- DbContext 或 UoW 需要注册到 InstancePerRequest()
- 你应该使用 OnRelease(context => context.SaveMyChangesIfEverythingIsOk()) native Autofac API
而不是使用 Owin 中间件
例如,这就是 RavenDb 的样子
builder.Register(x =>
{
var session = x.Resolve<IDocumentStore>().OpenAsyncSession();
session.Advanced.UseOptimisticConcurrency = true;
return session;
})
.As<IAsyncDocumentSession>()
.InstancePerRequest()
.OnRelease(x =>
{
x.SaveChangesAsync();
x.Dispose();
});
我想在每个请求结束时为我的项目 SaveChanges
添加一些基础设施到我的数据库上下文中。
所以我创建了一个简单的 Owin 中间件
app.Use(async (ctx, req) => {
await req();
var db = DependencyResolver.Current.GetService<MyDbContext>();
await db.SaveChangesAsync();
});
这不起作用并抛出错误
Instances cannot be resolved and nested lifetimes cannot be created from this LifetimeScope as it has already been disposed.
如果我在完成请求之前解析数据库
app.Use(async (ctx, req) => {
var db = DependencyResolver.Current.GetService<MyDbContext>();
await req();
await db.SaveChangesAsync();
});
它不会抛出错误,但它也不起作用(因为更改未保存到数据库中,在调试器中查看数据库显示 DbSet
的 Local
属性 抛出一个关于它被处理的 InvalidOperationException
。
我试过使用和不使用异步,在 autofac 配置之前和之后注册中间件 (app.UseAutofacMiddleware(container)
) 并直接从 Owin 环境解析 LifetimeScope
。都给我相同的结果。
我以前用 Structuremap 做过类似的事情,但似乎无法找到让 Autofac 正常运行的正确方法。
史蒂文关于您不应该提交请求处理这一事实是正确的,因为您无法确定您是否真的想在那里提交,除非您从 DbContext 中抽象出您的 UoW 并在那里保留一个成功属性,检查是否关于处置和有条件地提交。
对于您的具体问题,有两点需要澄清。
- DbContext 或 UoW 需要注册到 InstancePerRequest()
- 你应该使用 OnRelease(context => context.SaveMyChangesIfEverythingIsOk()) native Autofac API 而不是使用 Owin 中间件
例如,这就是 RavenDb 的样子
builder.Register(x =>
{
var session = x.Resolve<IDocumentStore>().OpenAsyncSession();
session.Advanced.UseOptimisticConcurrency = true;
return session;
})
.As<IAsyncDocumentSession>()
.InstancePerRequest()
.OnRelease(x =>
{
x.SaveChangesAsync();
x.Dispose();
});