【发布时间】:2021-02-10 12:23:41
【问题描述】:
我有一个复杂的查询,似乎会导致我的应用程序内存出现内存泄漏。
据我了解,查询结果被缓存,因此每次执行查询时都不需要进行此处理。 https://docs.microsoft.com/en-us/ef/core/querying/how-query-works
但是看起来查询正在为每个登录到系统的用户缓存。从内存转储看来,我们为同一个查询准备了数千个已编译的查询缓存对象。
查询如下所示。
public async Task<IList<EmployeeInboxMessage>> GetEmployeeMessagesAsync(long employeeId)
{
return await (from message in this.Repository.Set
join userStep in this.Repository.Context.Set<UserWorkflowHeaderStep>() on message.UserWorkflowStepId equals userStep.UserWorkflowStepId into userSteps
from userStep in userSteps.DefaultIfEmpty()
join acceptedStep in this.Repository.Context.Set<CompanyWorkflowStep>() on userStep.AcceptedStepId equals acceptedStep.WorkflowStepId into acceptedSteps
from acceptedStep in acceptedSteps.DefaultIfEmpty()
join rejectedStep in this.Repository.Context.Set<CompanyWorkflowStep>() on userStep.RejectedStepId equals rejectedStep.WorkflowStepId into rejectedSteps
from rejectedStep in rejectedSteps.DefaultIfEmpty()
let step =
message.InboxEntryType == InboxEntryType.Claims ||
message.InboxEntryType == InboxEntryType.AdvancedLeave ||
message.InboxEntryType == InboxEntryType.ChangeRequest
? new WorkflowHeaderStep
{
WorkflowItem = userStep.WorkflowItem,
AcceptedStepId = userStep.AcceptedStepId,
AcceptedStep = acceptedStep == null ? null : new WorkflowStep
{
OnApprovalActionId = acceptedStep.OnApprovalActionId,
OnRejectionAction = acceptedStep.OnRejectionAction,
OrderNumber = acceptedStep.OrderNumber
},
RejectedStepId = userStep.RejectedStepId,
RejectedStep = rejectedStep == null ? null : new WorkflowStep
{
OnApprovalActionId = rejectedStep.OnApprovalActionId,
OnRejectionAction = rejectedStep.OnRejectionAction,
OrderNumber = rejectedStep.OrderNumber
}
}
: null
let employeeName = string.IsNullOrWhiteSpace(message.OBOEmployee.PreferredName)
? message.OBOEmployee.FullName
: message.OBOEmployee.PreferredName + " " + message.OBOEmployee.LastName
where message.EmployeeId == employeeId
orderby message.EffectiveDate
select new EmployeeInboxMessage
{
Message = message,
UserStep = step,
UserId = message.UserId,
UserName = message.User.FullName,
EmployeeName = message.OBOEmployeeId.HasValue
? employeeName
: message.User.FullName,
RelatedPrimaryKey =
message.InboxEntryType == InboxEntryType.Claims ||
message.InboxEntryType == InboxEntryType.AdvancedLeave ||
message.InboxEntryType == InboxEntryType.ChangeRequest
? userStep.RelatedPrimaryKey
: message.UserWorkflowStepId!.Value,
StartUserCompanyId = message.StartUser.CompanyId
}).ToListAsync();
}
【问题讨论】:
-
1.更新到 EF Core 3.x 或 5 2. EF Core 本身不缓存查询结果 3. 如果仍有问题,请将问题发布到 EF Core 存储库。
-
我们有一个活动系统,很遗憾我们不能只更新到核心 3。但我们正在更新过程中。如果 E 核心没有缓存查询,它是什么?文档声明“结果被缓存,因此每次执行查询时都不需要进行此处理”
-
仅缓存具有 PK 的实体。如果您对此有疑问 - 始终重新创建 DataContext。
-
在 .netcore 中,您通过依赖注入注册 DBContext。至少这是默认行为。您还将它注册为作用域,这意味着在每个请求上都会创建 DBContext。所以我不需要重新创建 DBContext 作为框架处理
-
确实如此。但我不知道你如何实例化上下文,所以这只是建议。编写简单的测试,运行此函数 100 次并检查 CompiledQuery 缓存发生了什么,如果它增长 - EF 有错误。由于一切都从 EF 2 更改为 EF 3,因此在当前版本中可能不是问题。
标签: linq .net-core entity-framework-core ef-core-2.2 dotmemory