entity-framework-core - EF Core 诊断 - 每个上下文实例的查询计数

标签 entity-framework-core

我正在尝试通过检查每个上下文实例进行了多少查询来检测 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/

相关文章:

c# - 克隆对象并将克隆保存到数据库会导致原始对象丢失关系数据

具有 Entity Framework 和 OData 过滤选项的 Azure 函数

c# - Entity Framework 7 未配置数据库提供程序 => 当迁移移动到另一个项目时

c# - Entity Framework Core 数据库第一种方法复数表名

c# - 对 DBSet、DBSet.AsQueryable() 或 DBSet.AsQueryable<T>() 进行过滤

c# - List.Foreach 在 Using block 中使用一次性项目

entity-framework - EF Core Code First - 聚簇索引和标识列

c# - 更新 EFCore 连接的通用方法

asp.net - 如何使用 ASP.NET Core 更新 mongo Db 集合中的嵌套 JSON 对象字段

c# - 在同一个 Asp.Net Core 2 解决方案中将 DbContext 注入(inject)类库项目