我有一个动作过滤器,将请求记录在数据库中。
我使用通常的构造注射器方法。
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);
}
但这会在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
据我所知,问题在于筛选器的生存期比上下文(设置为“瞬态”)的生存期更长。
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")), ServiceLifetime.Transient);
那我应该如何注入DbContext?
答案 0 :(得分:1)
您正在使用Task.Run(() => loggerRepository.InsertServerCallLog(serverLog));
,该上下文将上下文分配给变量loggerRepository
,并告诉它在线程池上运行,从而使方法继续执行。该方法很有可能在线程池完成执行和对象被处置之前就退出,只需让对InsertServerCallLog
的调用在主线程上运行,以使执行直到完成该方法后才继续执行