[英]ObjectDisposedException when trying to write to database inside request pipeline
我正在嘗試添加一些代碼,以將每個請求的DateTime值保存到數據庫。
我向app.Use()
Configure方法添加了一些代碼。
這是我的配置方法:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, MyDbContext db)
{
var appSettings = Configuration.GetSection("AppSettings").Get<AppSettings>();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors(builder =>
builder.WithOrigins(appSettings.BaseUrls.WebAllowCors)
.AllowAnyHeader().AllowAnyMethod()
);
app.UseAuthentication();
app.Use(async (context,next) =>
{
var id = context.User.Claims.First(x => x.Type == "sub").Value;
var user = db.AspNetUsers.Find(id);
user.LastAccessed = DateTime.Now;
await db.SaveChangesAsync();
await next();
});
app.UseMvc();
}
但是我得到了錯誤:
處理請求時發生未處理的異常。
ObjectDisposedException:無法訪問已處置的對象。 導致此錯誤的常見原因是,處理從依賴項注入中解決的上下文,然后稍后嘗試在應用程序中的其他位置使用相同的上下文實例。 如果在上下文上調用Dispose()或將上下文包裝在using語句中,則可能會發生這種情況。 如果使用依賴項注入,則應讓依賴項注入容器負責處理上下文實例。 對象名稱:“ MyDbContext”。
在每個請求上寫入數據庫的正確方法是什么?
發生這種情況是因為您使用的示波器不正確。 您正在從configure方法獲取數據庫實例。 但這在啟動時被調用一次。
您應該執行以下操作:
app.Use(async (context, next) =>
{
var id = context.User.Claims.First(x => x.Type == "sub").Value;
using(var db = context.RequestServices.GetService<MyDbContext>())
{
var user = db.AspNetUsers.Find(id);
user.LastAccessed = DateTime.Now;
await db.SaveChangesAsync();
}
await next();
});
希望此代碼段對您有所幫助。 如果您需要任何澄清,我將很樂意回答您的問題。
可以有多種方法來處理這種情況。 我會使用的一個方法是創建自定義過濾器,並使用自定義過濾器注釋方法或操作以更新用戶的上次訪問時間。
public class UpdateLastAccessFilter : ActionFilterAttribute, IActionFilter
{
void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
{
// TODO: Add your action filter's tasks here
// Log Action Filter call
using (dbEntities context = new dbEntities())
{
var id = context.User.Claims.First(x => x.Type == "sub").Value;
var user = db.AspNetUsers.Find(id);
user.LastAccessed = DateTime.Now;
await db.SaveChangesAsync();
OnActionExecuting(filterContext);
}
}
}
然后裝飾您需要記錄訪問時間的方法或控制器。
[UpdateLastAccessFilter]
public class StoreController : Controller
{
...
}
這可能是因為MyDbContext
是可拋棄的,並且每次需要時都需要包裝在MyDbContext
中。
試試看,看看是否可行:
using (var context = db)
{
context.AspNetUsers.Find(id);
}
您可能需要對db
任何后續使用執行相同的操作。
我假設MyDbContext
已在StartUp.cs
ConfigureService(IServiceCollection services)
函數中注冊到IoC? 像這樣:
services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(Configuration.GetSection("ConnectionStrings:Sql").Value)
);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.