简体   繁体   English

如何在动作过滤器中注入DbContext

[英]How to inject DbContext in an Action Filter

I have an action filter which logs the request in a database. 我有一个动作过滤器,将请求记录在数据库中。

I use the usual construction injector method. 我使用通常的构造注射器方法。

public ServerLogFilterAttribute(OrderEntryContext context)
{
  this.context = context;
}

public override void OnActionExecuting(ActionExecutingContext context)
{
    var descriptor = context.ActionDescriptor;
    if (descriptor != null && descriptor.RouteValues.Count > 0)
    {
        var actionName = descriptor.RouteValues["action"];
        var controllerName = descriptor.RouteValues["controller"];

        if (context.HttpContext.User != null && context.HttpContext.User.Identity != null)
        {
            var claimsIdentity = context.HttpContext.User.Identity as ClaimsIdentity;

            if (claimsIdentity != null && claimsIdentity.IsAuthenticated)
            {
                var username = claimsIdentity.FindFirst(ClaimTypes.NameIdentifier).Value;
                var userId = claimsIdentity.Claims.First(c => c.Type == "userId").Value;

                var serverLog = new ServerLog()
                {
                    AspNetUserId = userId,
                    Controller = controllerName,
                    Action = actionName,
                    TimeStamp = DateTime.Now
                };

                LoggerRepository loggerRepository = new LoggerRepository(this.context);
                Task.Run(() => loggerRepository.InsertServerCallLog(serverLog));
            }
        }
    }

    base.OnActionExecuting(context);

}

But this throws an exception during SaveChanges(): 但这在SaveChanges()期间引发异常:

System.ObjectDisposedException
  HResult=0x80131622
  Message=Cannot access a disposed object. 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. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
  Source=Microsoft.EntityFrameworkCore
  StackTrace:
   at Microsoft.EntityFrameworkCore.DbContext.CheckDisposed()
   at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
   at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
   at Microsoft.EntityFrameworkCore.DbContext.<SaveChangesAsync>d__48.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at GGL.OrderEntry.Data.OrderEntryContext.<SaveChangesAsync>d__251.MoveNext() in C:\Dev\GGL\GGL.OrderEntry\GGL.OrderEntry.Data\Context\OrderEntryContext.Partial.cs:line 306

As far as I have been able to figure, the issue is that the lifetime of the Filter is longer than the lifetime of the context (which was set to "Transient) 据我所知,问题在于筛选器的生存期长于上下文的生存期(已设置为“瞬态”)

options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")), ServiceLifetime.Transient);

How then should I be injecting the DbContext? 那我应该如何注入DbContext?

You're using Task.Run(() => loggerRepository.InsertServerCallLog(serverLog)); 您正在使用Task.Run(() => loggerRepository.InsertServerCallLog(serverLog)); which assigns the context to variable loggerRepository , and telling it to run on the thread pool, thus letting the method continue execution. 它将上下文分配给变量loggerRepository ,并告诉它在线程池上运行,从而使方法继续执行。 More than likely the method exits before the thread pool finishes execution and the object has been disposed, just let the call to InsertServerCallLog run on the main thread so that execution does not continue until it has finished that method 该方法很有可能在线程池完成执行和对象被处置之前就退出,只需让对InsertServerCallLog的调用在主线程上运行,以便在完成该方法之前不会继续执行

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM