【发布时间】:2021-08-09 16:40:22
【问题描述】:
我认为我的 DbContext 初始化存在问题。我知道很多人都在谈论它,但我可能做错了什么,因为这些答案与大上下文或大表(许多列或大量数据)有关。
在我的例子中,用户表由 30 列组成,而我只有 30 000 行。
当我启动应用程序或它被回收时,需要 22 秒才能获得第一个查询结果。
我添加了一些日志,据我了解,查询显然不是问题(您可以在下面找到这些日志)。当我将查询复制粘贴到 SSMS 中时,我会在不到一秒的时间内得到结果。第一次执行后,查询和一切几乎是“立即的”。所以,t问题将来自于上下文的初始化。
我用一些预编译的视图或类似的东西读到它可能会更快。我真的很惊讶,只有那张“小”桌子我需要特殊处理才能获得可接受的性能。这就是为什么我认为我错过了一些东西。
我的应用程序在 .net core 3.1 中,我使用的是 Entity Framework Core 5.0.8
在我的 ConfigureService 中,我有:
services.AddDbContext<DbContext>(options =>
options.UseSqlServer(serviceConfiguration.ConnectionString));
我的 DbContext:
public class DbContext : DbContext
{
private readonly ILoggingService<DbContext> _loggingService;
private readonly ILoggerFactory _loggerFactory;
public virtual DbSet<User> Users { get; set; }
public DbContext(DbContextOptions<DbContext> options, ILoggingService<DbContext> loggingService, ILoggerFactory loggerFactory)
: base(options)
{
_loggingService = loggingService;
_loggerFactory = loggerFactory;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.EnableSensitiveDataLogging();
optionsBuilder.EnableServiceProviderCaching();
optionsBuilder.UseLoggerFactory(_loggerFactory);
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
_loggingService.LogError("Begin model creating");
modelBuilder.Entity<User>(entity =>
{
entity.HasKey(u => u.UserId);
entity.ToTable("User");
});
_loggingService.LogError("End model creating");
}
}
2021-08-09 15:28:30.830|WARN|Microsoft.EntityFrameworkCore.Model.Validation|敏感数据记录已启用。日志条目和异常消息可能包括敏感的应用程序数据;此模式只能在开发期间启用。|url:|action:UsersController.CreateUser
2021-08-09 15:28:30.957|INFO|Microsoft.EntityFrameworkCore.Infrastructure|Entity Framework Core 5.0.8 使用提供程序“Microsoft.EntityFrameworkCore.SqlServer”初始化“DbContext”,选项:SensitiveDataLoggingEnabled |url:|action :UsersController.CreateUser
2021-08-09 15:28:52.702|INFO|Microsoft.EntityFrameworkCore.Database.Command|执行 DbCommand (53ms) [Parameters=[@__username_0='' (Size = 4000)], CommandType='"Text "', 命令超时='30'] SELECT TOP(1) [u].[UserId], [u].[Email], [u].[Firstname], [u].[Username] FROM [用户] AS [u] WHERE ([u].[Username] = @__username_0) AND ([u].[StatusId] > 0)|url:|action:UsersController.CreateUser
2021-08-09 15:28:52.973|INFO|Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker|在 23053.3706ms|url:|action:UsersController.CreateUser 中执行的操作 UsersController.CreateUser
【问题讨论】:
-
您是否对应用程序进行了概要分析以查看时间花费在哪里?
-
这里的未知数真的太多了。可能只是你的机器很慢。
-
“据我了解,查询不是问题”。 EF Core 通常不会初始化上下文,直到您尝试将其用于某事;我从日志中可以看到,从实际初始化到它完成运行查询需要大约 22 秒;您如何确定查询不是问题?如果您在本地安装了用于开发/测试的 SQL Server,则可以使用 Developer 版本,其中包括 SQL Server 分析器。您可以使用它来查看该 SQL 语句是否真的很慢,尽管 30,000 行并不多。
-
我在我的问题中添加了一些精确度。就像我所说的那样,它与我的机器无关,因为在第一次午餐后它比第一次快得多,所以即使我的机器速度很慢,仍然存在很大差异(1 秒与 22 秒)。 “据我了解,查询不是问题”-> 在 SSMS 中复制/粘贴查询时,它总是很快。所以它纯粹与.net代码有关。
-
如果关闭日志记录会发生什么?这可能会增加一次性初始化成本。 DbContext 初始化成本通常取决于表的数量/正在初始化的架构的复杂性,这对于您的示例来说应该不是问题。如果像日志记录这样的事情确实会产生类似的一次性成本,那么在这些情况下应该考虑相同的“热身”过程。 (本质上是在应用程序/站点的最早初始化点启动一个简单的 Count()/Any() 查询。)
标签: performance entity-framework asp.net-core .net-core entity-framework-core