gpt4 book ai didi

c# - 如何测试 Entity Framework 中随时间发生的查询数量?

转载 作者:行者123 更新时间:2023-11-30 14:50:57 26 4
gpt4 key购买 nike

对于某些背景 - 我正在编写一些 Entity Framework 功能的抽象,以使那些使用数据访问层的人的工作更容易一些。我通过代理/包装器执行此操作,现在我想测试 EF 的 Include() 是否成功使用。 (但这与这里的特定问题无关(只是想避免人们建议“不要测试 EF 功能”(我将 Include 方法委托(delegate)给 EF,这正是我实际测试的)))

理想情况下,我想定义一个 block (可能通过 using)并让该 block 计算该 block 内发生的查询的数量。

使用一些伪代码,这是我想要的行为:

var user = new User(id);


using(var queryCounter = new QueryCounter()){
user.Books.SelectMany(b => b.Pages);


Assert.Equal(2, queryCounter.NumberOfDetectedQueries);
// the above assert would fail, due to not using the `Include` keyword.
// as the two queries should be to select books and page ids and
// then to actually select the pages
}

有没有办法实现类似上面的查询计数?


更新:

感谢@Ilya Chumakov 提供对查询拦截器的见解。我已经能够通过一个额外的类获得上面示例中的语法:

public class QueryCounter : IDisposable
{
public int Count => GlobalCounter.QueryCount;

public QueryCounter()
{
GlobalCounter.QueryCount = 0;
GlobalCounter.Active = true;
}

public void Dispose()
{
GlobalCounter.Active = false;
GlobalCounter.QueryCount = 0; //
}
}

然后向 GlobalCounter 添加一个事件字段

public static class GlobalCounter
{
public static int QueryCount = 0;
public static bool Active = false;
}

像这样修改每个拦截器方法:

#if DEBUG
if (!GlobalCounter.Active) return;
GlobalCounter.QueryCount++;
// or whatever output class/method works for you
Trace.Write("Current Query Count: " + GlobalCounter.QueryCount + " -- ");
Trace.WriteLine(command.CommandText);
#endif

现在,我的测试看起来像这样:

        using (var counter = new QueryCounter())
{
var pages = user.Books.First().Pages;
Assert.Equal(1, counter.Count);
}

最佳答案

可以用拦截器来实现:

class EfCommandInterceptor : IDbCommandInterceptor
{
public void NonQueryExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
GlobalCounter.QueryCount++;
}

public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
GlobalCounter.QueryCount++;
}

public void ScalarExecuted(System.Data.Common.DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
GlobalCounter.QueryCount++;
}

//other methods are empty
}

GlobalCounter 类保存全局变量:

static class GlobalCounter
{
public static int QueryCount { get; set; }
}

注册拦截器:

public class EntityConfigiration : DbConfiguration
{
public EntityConfigiration()
{
this.AddInterceptor(new EfCommandInterceptor());
}
}

EntityConfiguration 类将自动注册。您可以改为在配置文件中注册拦截器。

Entity Framework Tutorial: Interception

Code-Based Configuration (EF6 onwards)

然后使用:

[Test]
public void CalculateQueryCount()
{
GlobalCounter.QueryCount = 0;

using (var context = new YourContext())
{
//queries
}

int actual = GlobalCounter.QueryCount;
}

EfCommandInterceptor 代码是单线程的。对于多线程测试,应该使用锁定(lockInterlocked.Increment 等)而不是 ++

关于c# - 如何测试 Entity Framework 中随时间发生的查询数量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35558897/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com