C# 尝试在请求管道内写入数据库时发生ObjectDisposedException
我正在尝试添加一些代码,以便在每次请求时将DateTime值保存到数据库中 我添加了一些代码,用C# 尝试在请求管道内写入数据库时发生ObjectDisposedException,c#,asp.net-core,.net-core,C#,Asp.net Core,.net Core,我正在尝试添加一些代码,以便在每次请求时将DateTime值保存到数据库中 我添加了一些代码,用app.Use()配置方法 这是我的配置方法: public void Configure(IApplicationBuilder app, IHostingEnvironment env, MyDbContext db) { var appSettings = Configuration.GetSection("AppSettings").Get<AppSettin
app.Use()
配置方法
这是我的配置方法:
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();
}
public void配置(IApplicationBuilder应用程序、IHostingEnvironment环境、MyDbContext数据库)
{
var appSettings=Configuration.GetSection(“appSettings”).Get();
if(env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors(builder=>
builder.WithOrigins(appSettings.BaseUrls.WebAllowCors)
.AllowAnyHeader().AllowAnyMethod()
);
app.UseAuthentication();
应用程序使用(异步(上下文,下一步)=>
{
var id=context.User.Claims.First(x=>x.Type==“sub”).Value;
var user=db.AspNetUsers.Find(id);
user.LastAccessed=DateTime.Now;
等待db.saveChangesSync();
等待下一个();
});
app.UseMvc();
}
但我得到了一个错误:
处理请求时发生未处理的异常
ObjectDisposedException:无法访问已处置的对象。此错误的一个常见原因是处理通过依赖项注入解析的上下文,然后在应用程序的其他位置尝试使用相同的上下文实例。如果对上下文调用Dispose(),或将上下文包装到using语句中,则可能会发生这种情况。如果您使用的是依赖项注入,那么应该让依赖项注入容器处理上下文实例。
对象名称:“MyDbContext”
在这里,对每个请求写入数据库的正确方法是什么?可以有多种方法来处理这种情况。我将使用的一种方法是创建自定义过滤器,并使用自定义过滤器注释方法或操作,以更新用户的上次访问时间
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
{
...
}
然后修饰需要记录访问时间的方法或控制器
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
{
...
}
处理这种情况有多种方法。我将使用的一种方法是创建自定义过滤器,并使用自定义过滤器注释方法或操作,以更新用户的上次访问时间
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
{
...
}
然后修饰需要记录访问时间的方法或控制器
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
是一次性的,每次需要时都需要包装在using中
试试这个,看看它是否有效:
using (var context = db)
{
context.AspNetUsers.Find(id);
}
您可能需要在以后使用db
时执行相同的操作
我假设
MyDbContext
已在StartUp.cs
ConfigureService(IServiceCollection服务)
功能中注册到IoC?大概是这样的:
services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(Configuration.GetSection("ConnectionStrings:Sql").Value)
);
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();
});
services.AddDbContext(选项=>
options.UseSqlServer(Configuration.GetSection(“ConnectionString:Sql”).Value)
);
这可能是因为MyDbContext
是一次性的,每次需要时都需要包装在using中
试试这个,看看它是否有效:
using (var context = db)
{
context.AspNetUsers.Find(id);
}
您可能需要在以后使用db
时执行相同的操作
我假设
MyDbContext
已在StartUp.cs
ConfigureService(IServiceCollection服务)
功能中注册到IoC?大概是这样的:
services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(Configuration.GetSection("ConnectionStrings:Sql").Value)
);
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();
});
services.AddDbContext(选项=>
options.UseSqlServer(Configuration.GetSection(“ConnectionString:Sql”).Value)
);
这可能是因为您使用的范围错误。
您正在从configure方法获取db实例。但这在启动时只调用一次
你应该这样做:
services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(Configuration.GetSection("ConnectionStrings:Sql").Value)
);
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();
});
app.Use(异步(上下文,下一步)=>
{
var id=context.User.Claims.First(x=>x.Type==“sub”).Value;
使用(var db=context.RequestServices.GetService())
{
var user=db.AspNetUsers.Find(id);
user.LastAccessed=DateTime.Now;
等待db.saveChangesSync();
}
等待下一个();
});
希望这个片段能帮助你。如果您需要任何澄清,我非常愿意回答您的问题。这可能是因为您使用的范围错误。 您正在从configure方法获取db实例。但这在启动时只调用一次 你应该这样做:
services.AddDbContext<MyDbContext>(options =>
options.UseSqlServer(Configuration.GetSection("ConnectionStrings:Sql").Value)
);
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();
});
app.Use(异步(上下文,下一步)=>
{
var id=context.User.Claims.First(x=>x.Type==“sub”).Value;
使用(var db=context.RequestServices.GetService())
{
var user=db.AspNetUsers.Find(id);
user.LastAccessed=DateTime.Now;
等待db.saveChangesSync();
}
等待下一个();
});
希望这个片段能帮助你。如果您需要任何澄清,我将非常乐意回答您的问题。哪一行引发异常?哪一行引发异常?我假设
MyDbContext
已在StartUp.cs
配置服务(IServiceCollection服务)
功能中注册到IoC?类似这样的内容:services.AddDbContext(options=>options.UseSql(Configuration.GetSection(“connectionString:Sql”).Value)
我假设MyDbContext
已在StartUp.cs
ConfigureService(iSeries收集服务)
功能中注册到IoC?类似这样的内容:services.AddDbContext(options=>options.UseSql(Configuration.GetSection(“connectionString:Sql”).Value)代码>谢谢,这解决了我的问题。Configure方法是配置管道,而不是实际的管道,因此当然上下文超出了我声明它的范围。事后看来,这是显而易见的。谢谢你的帮助!作为旁注,我不得不删除using语句,因为它在其他地方导致了相同的错误,因为它正在处理仍然需要的上下文