我正在尝试通过检查每个上下文实例进行了多少查询来检测 EF。我们通常不希望对上下文进行超过 10 个左右的查询,因此我想用它来检查上下文是否被滥用,例如在循环内进行查询调用,这会导致明显的性能问题。
我基本上想说的是,如果针对任何给定上下文的查询次数 > X,则记录错误甚至抛出异常。
我能找到的最接近的是使用 Diagnostic Listeners对于事件 ID:RelationalEventId.CommandExecuted.Name,但是事件数据中没有对上下文的引用,因此无法在每个上下文的基础上对其进行跟踪。事件计数器也不是真正可行的解决方案,因为它们是全局计数器。
有谁知道我想做的事情是否可以通过其他方式实现?
提前致谢!
最佳答案
我找到了一个解决方案,事实证明,从 EF Core 3+ 开始,Context 实例被添加到 DbCommandInterceptor 中的 CommandCorrelatedEventData,以及 DbContext 上的 ContextId,这为您提供了跟踪查询计数所需的一切。
这是一个限制每个上下文实例运行的命令数量的拦截器示例:
public class QueryInterceptor : DbCommandInterceptor
{
// TODO: Use an expiring cache
private readonly ConcurrentDictionary<DbContextId, int> _queryCountsPerContext = new();
public override InterceptionResult<DbCommand> CommandCreating(CommandCorrelatedEventData eventData, InterceptionResult<DbCommand> result)
{
OnQueryExecuted(eventData);
return base.CommandCreating(eventData, result);
}
private void OnQueryExecuted(CommandCorrelatedEventData eventData)
{
if (eventData.Context == null)
{
return;
}
if (!_queryCountsPerContext.TryGetValue(eventData.Context.ContextId, out var count))
{
count = 0;
}
count++;
_queryCountsPerContext[eventData.Context.ContextId] = count;
if (count > Constants.QueryLimitPerContextInstance)
{
throw new InvalidOperationException($"Too many queries for context instance! Limit: {Constants.QueryLimitPerContextInstance}");
}
}
}
要点和完整示例:https://gist.github.com/cjbhaines/acdb69a47520e8b4b43b03a754150bc6
关于entity-framework-core - EF Core 诊断 - 每个上下文实例的查询计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66170534/