计算 EF Core 支持的身份系统中的查询数
Count number of queries in EF Core backed Identity system
我 运行宁 ASP.NET Core Identity(UserManager<TUser>
和爵士乐),由 EF Core 商店提供支持。我最近在我的应用程序中遇到了一个错误,其中控制器端点导致对 UserManager<T>.UpdateAsync(...)
.
的调用过多
因为我已经进行了集成测试(使用 WebApplicationFactory<TStartup>
设置和 UseInMemoryDatabase(...)
),所以我很想编写一个 integration/smoke 测试,如果控制器端点运行时会警告我超出其查询预算。
基本上,我很想写(但不会写)这个测试:
public class FooControllerTests : IClassFixture<WebApplicationFactory>
{
private readonly WebApplicationFactory _factory;
public FooControllerTests(WebApplicationFactory factory)
{
_factory = factory;
}
[Fact]
public async Task Bar_WhenCalled_StaysWithinQueryBudget()
{
using var scope = _factory.Server.Host.Services.CreateScope();
var services = scope.ServiceProvider;
var dbContext = services.GetRequiredService<MyDbContext>();
var countBefore = dbContext.SomehowGetCurrentQueryCount(); // ??
var httpClient = _factory.CreateClient();
var _ = httpClient.PostAsJsonAsync("/foo/bar", new { data = "something" });
var countAfter = dbContext.SomehowGetCurrentQueryCount(); // ??
var budgetForEndpoint = 3;
Assert.True(countAfter - countBefore > budgetForEndpoint);
}
}
但重要的是精神:我想要一个冒烟测试来检查我是否不会在未来犯同样的错误并且有一个导致太多(更新)查询的错误。
我试过编写 a DbCommandInterceptor
并将其添加到我的 AddDbContext
调用中,但似乎通过 AddEntityFrameworkStores<TDbContext>(...)
添加的 Store
与此隔离,因为我的 CommandCreating
处理程序从未被调用过。
如果查询 运行 通过 Identity EF 核心存储,我如何检查我的端点是否在查询预算内?
我目前正在使用 ASP.NET Core 3.1 和 EF Core 3.1,但我愿意升级以获得此功能。
I've tried writing a DbCommandInterceptor and added it to my AddDbContext call, but it seems the Store that was added via AddEntityFrameworkStores(...) is isolated from that, as my CommandCreating handler was never called.
这就是方法。以下摘自Introduction to Identity on ASP.NET Core: Configure Identity services:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
只需添加拦截器即可:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
.AddInterceptors(new QueryCountingCommandInterceptor())
);
请注意,您提到使用 UseInMemoryDatabase()
,您可能只在 WebApplicationFactory<TStartup>
class 中这样做。如果是这样,您也需要在那里添加拦截器:
public class WebApplicationFactory : WebApplicationFactory<Startup>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(s => s.AddDbContext<ApplicationDbContext>(options =>
{
options.UseInMemoryDatabase("integration-tests");
options.AddInterceptors(new MyInterceptor());
}));
}
}
这很好,因为您可以只为测试添加拦截器,而不是为生产代码添加拦截器运行。
我 运行宁 ASP.NET Core Identity(UserManager<TUser>
和爵士乐),由 EF Core 商店提供支持。我最近在我的应用程序中遇到了一个错误,其中控制器端点导致对 UserManager<T>.UpdateAsync(...)
.
因为我已经进行了集成测试(使用 WebApplicationFactory<TStartup>
设置和 UseInMemoryDatabase(...)
),所以我很想编写一个 integration/smoke 测试,如果控制器端点运行时会警告我超出其查询预算。
基本上,我很想写(但不会写)这个测试:
public class FooControllerTests : IClassFixture<WebApplicationFactory>
{
private readonly WebApplicationFactory _factory;
public FooControllerTests(WebApplicationFactory factory)
{
_factory = factory;
}
[Fact]
public async Task Bar_WhenCalled_StaysWithinQueryBudget()
{
using var scope = _factory.Server.Host.Services.CreateScope();
var services = scope.ServiceProvider;
var dbContext = services.GetRequiredService<MyDbContext>();
var countBefore = dbContext.SomehowGetCurrentQueryCount(); // ??
var httpClient = _factory.CreateClient();
var _ = httpClient.PostAsJsonAsync("/foo/bar", new { data = "something" });
var countAfter = dbContext.SomehowGetCurrentQueryCount(); // ??
var budgetForEndpoint = 3;
Assert.True(countAfter - countBefore > budgetForEndpoint);
}
}
但重要的是精神:我想要一个冒烟测试来检查我是否不会在未来犯同样的错误并且有一个导致太多(更新)查询的错误。
我试过编写 a DbCommandInterceptor
并将其添加到我的 AddDbContext
调用中,但似乎通过 AddEntityFrameworkStores<TDbContext>(...)
添加的 Store
与此隔离,因为我的 CommandCreating
处理程序从未被调用过。
如果查询 运行 通过 Identity EF 核心存储,我如何检查我的端点是否在查询预算内?
我目前正在使用 ASP.NET Core 3.1 和 EF Core 3.1,但我愿意升级以获得此功能。
I've tried writing a DbCommandInterceptor and added it to my AddDbContext call, but it seems the Store that was added via AddEntityFrameworkStores(...) is isolated from that, as my CommandCreating handler was never called.
这就是方法。以下摘自Introduction to Identity on ASP.NET Core: Configure Identity services:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
只需添加拦截器即可:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
.AddInterceptors(new QueryCountingCommandInterceptor())
);
请注意,您提到使用 UseInMemoryDatabase()
,您可能只在 WebApplicationFactory<TStartup>
class 中这样做。如果是这样,您也需要在那里添加拦截器:
public class WebApplicationFactory : WebApplicationFactory<Startup>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(s => s.AddDbContext<ApplicationDbContext>(options =>
{
options.UseInMemoryDatabase("integration-tests");
options.AddInterceptors(new MyInterceptor());
}));
}
}
这很好,因为您可以只为测试添加拦截器,而不是为生产代码添加拦截器运行。