简体   繁体   English

尝试在请求管道内写入数据库时​​出现ObjectDisposedException

[英]ObjectDisposedException when trying to write to database inside request pipeline

I am trying to add some code that will save a DateTime value to database on every request. 我正在尝试添加一些代码,以将每个请求的DateTime值保存到数据库。

I added some code to Configure method with app.Use() . 我向app.Use() Configure方法添加了一些代码。

This is my configure method: 这是我的配置方法:

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();
}

But I get the error: 但是我得到了错误:

An unhandled exception occurred while processing the request. 处理请求时发生未处理的异常。

ObjectDisposedException: Cannot access a disposed object. ObjectDisposedException:无法访问已处置的对象。 A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. 导致此错误的常见原因是,处理从依赖项注入中解决的上下文,然后稍后尝试在应用程序中的其他位置使用相同的上下文实例。 This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. 如果在上下文上调用Dispose()或将上下文包装在using语句中,则可能会发生这种情况。 If you are using dependency injection, you should let the dependency injection container take care of disposing context instances. 如果使用依赖项注入,则应让依赖项注入容器负责处理上下文实例。 Object name: 'MyDbContext'. 对象名称:“ MyDbContext”。

What is correct way here to write to database on every request? 在每个请求上写入数据库的正确方法是什么?

this can happen because you are using the scope wrong. 发生这种情况是因为您使用的示波器不正确。 You are getting the db instance from your configure method. 您正在从configure方法获取数据库实例。 But this is called once at the startup. 但这在启动时被调用一次。

You should do something like this: 您应该执行以下操作:

  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();
        });

Hope this snippet helps you. 希望此代码段对您有所帮助。 If you need any clarification i would be more than willing to answer your questions. 如果您需要任何澄清,我将很乐意回答您的问题。

There can be multiple ways to handle this situation. 可以有多种方法来处理这种情况。 One that i would go with, is creating custom filters and annotating the methods or operations with a custom filter to update user's last access time. 我会使用的一个方法是创建自定义过滤器,并使用自定义过滤器注释方法或操作以更新用户的上次访问时间。

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);
        }
    }
}

and then decorate the methods or controllers for which you need to log access time. 然后装饰您需要记录访问时间的方法或控制器。

[UpdateLastAccessFilter]
public class StoreController : Controller
{
    ...
}

More Details on custom filter 有关自定义过滤器的更多详细信息

This may be because MyDbContext is disposable and needs to be wrapped in a using every time you need it. 这可能是因为MyDbContext是可抛弃的,并且每次需要时都需要包装在MyDbContext中。

Try this and see if it works: 试试看,看看是否可行:

using (var context = db)
{
    context.AspNetUsers.Find(id);
}

You may need to do the same with any subsequent use of db . 您可能需要对db任何后续使用执行相同的操作。

I'm assuming that MyDbContext has been registered to the IoC in the StartUp.cs ConfigureService(IServiceCollection services) function? 我假设MyDbContext已在StartUp.cs ConfigureService(IServiceCollection services)函数中注册到IoC? Something like this: 像这样:

services.AddDbContext<MyDbContext>(options =>
    options.UseSqlServer(Configuration.GetSection("ConnectionStrings:Sql").Value)
);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 尝试上传文件时出现ObjectDisposedException - ObjectDisposedException when trying to upload a file 尝试在 controller 内调用任务(即发即忘)并更改实体的 state 时出现 ObjectDisposedException - ObjectDisposedException when trying to call a task (fire and forget) inside controller and change state of entity 尝试列出对象时出现System.ObjectDisposedException - System.ObjectDisposedException when trying to list an object 尝试将文件保存到DbContext时抛出ObjectDisposedException - ObjectDisposedException thrown when trying to save files to a DbContext 尝试从SQLiteDataReader读取时遇到ObjectDisposedException - Encountering ObjectDisposedException when trying to read from SQLiteDataReader System.ObjectDisposedException 尝试访问 DataContext 时 - System.ObjectDisposedException when trying to access DataContext 尝试从List接收数据时System.ObjectDisposedException - System.ObjectDisposedException when trying to receive the data from a List 尝试传递 id 时出现 ASP.NET MVC ObjectDisposedException - ASP.NET MVC ObjectDisposedException when trying to pass id 尝试以自己的using语句访问MemoryStream时,MemoryStream抛出ObjectDisposedException - MemoryStream throws ObjectDisposedException when trying to access it in its own using statement 尝试使用异步方法访问Thread.CurrentPrincipal时出现ObjectDisposedException - ObjectDisposedException when trying to access Thread.CurrentPrincipal with async method
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM