Linq EF Core复杂查询将针对参数的每个变化进行缓存

Linq EF Core复杂查询将针对参数的每个变化进行缓存,linq,.net-core,entity-framework-core,ef-core-2.2,dotmemory,Linq,.net Core,Entity Framework Core,Ef Core 2.2,Dotmemory,我有一个复杂的查询,它似乎会导致我的应用程序内存出现内存泄漏 据我所知,查询结果是缓存的,因此不需要每次执行查询时都进行此处理 但它看起来是这样的:对于登录到系统中的每个用户,查询都会被缓存。从内存转储来看,似乎同一查询有数千个已编译查询缓存对象 查询如下所示 public async Task<IList<EmployeeInboxMessage>> GetEmployeeMessagesAsync(long employeeId) {

我有一个复杂的查询,它似乎会导致我的应用程序内存出现内存泄漏

据我所知,查询结果是缓存的,因此不需要每次执行查询时都进行此处理

但它看起来是这样的:对于登录到系统中的每个用户,查询都会被缓存。从内存转储来看,似乎同一查询有数千个已编译查询缓存对象

查询如下所示

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();
        }
public异步任务GetEmployeeMessagesAsync(长employeeId)
{
返回等待(来自this.Repository.Set中的消息)
将message.UserWorkflowStepId等于userStep.UserWorkflowStepId的.Repository.Context.Set()中的userStep连接到userSteps中
来自userSteps.DefaultIfEmpty()中的userStep
将userStep.AcceptedStepId等于acceptedStep.WorkflowStepId的.Repository.Context.Set()中的acceptedStep加入acceptedSteps
从acceptedSteps.DefaultIfEmpty()中的acceptedStep
将userStep.RejectedStepId上的.Repository.Context.Set()中的rejectedStep连接到rejectedSteps中等于rejectedStep.WorkflowStepId
从rejectedSteps.DefaultIfEmpty()中的rejectedStep
让开=
message.InboxEntryType==InboxEntryType.Claimes||
message.InboxEntryType==InboxEntryType.AdvancedLeave||
message.InboxEntryType==InboxEntryType.ChangeRequest
?新的WorkflowHeaderStep
{
WorkflowItem=userStep.WorkflowItem,
AcceptedStepId=userStep.AcceptedStepId,
AcceptedStep=AcceptedStep==null?null:新工作流步骤
{
OnApprovalActionId=acceptedStep.OnApprovalActionId,
OnRejectionAction=acceptedStep.OnRejectionAction,
OrderNumber=acceptedStep.OrderNumber
},
RejectedStepId=userStep.RejectedStepId,
RejectedStep=RejectedStep==null?null:新工作流步骤
{
OnApprovalActionId=rejectedStep.OnApprovalActionId,
OnRejectionAction=rejectedStep.OnRejectionAction,
OrderNumber=rejectedStep.OrderNumber
}
}
:null
让employeeName=string.IsNullOrWhiteSpace(message.OBOEmployee.PreferredName)
?message.OBOEmployee.FullName
:message.OBOEmployee.PreferredName+“”+message.OBOEmployee.LastName
其中message.EmployeeId==EmployeeId
orderby message.EffectiveDate
选择new EmployeeInboxMessage
{
消息=消息,
UserStep=step,
UserId=message.UserId,
用户名=message.User.FullName,
EmployeeName=message.OBOEmployeeId.HasValue
?雇员姓名
:message.User.FullName,
相关主键=
message.InboxEntryType==InboxEntryType.Claimes||
message.InboxEntryType==InboxEntryType.AdvancedLeave||
message.InboxEntryType==InboxEntryType.ChangeRequest
?userStep.RelatedPrimaryKey
:message.UserWorkflowStepId!。值,
StartUserCompanyId=message.StartUser.CompanyId
}).ToListAsync();
}

对于EF来说,创建单个CompiledQueryCache对象的查询似乎太复杂了,它正在为您传递的每个“employeeId”添加缓存版本。看起来已经有27804个版本了

如果您重新构造查询,那么它可能会解决您的问题。尝试删除“let step=…”和“let employeeName=…”。最糟糕的情况是,您需要创建原始SQL或视图

没有太多文档说明EF如何创建查询缓存(我找不到任何文档)。你可能永远不会知道你的问题到底是什么,除非一些EF创建者提供一些输入,或者你可以随时查看他们的代码


如果在更改查询后仍有问题,最好使用efcore记录问题。更新到EF Core 3.x或5.2。查询结果不由EF Core本身缓存3。如果您仍然有问题,请将问题发布到EF Core存储库。不幸的是,我们有一个活动系统,不能只更新到Core 3。但我们正在更新。如果E core没有缓存查询,它是什么?文档声明“缓存结果,因此不需要每次执行查询时都进行此处理”仅缓存具有PK的实体。如果您对此有问题,请始终重新创建DataContext。在.netcore中,您可以通过依赖项注入注册DBContext。至少这是默认行为。您还将其注册为作用域,这意味着将在每个请求上创建DBContext。所以我不需要重新创建它