如何在 Entity Framework Core 中利用 LINQ 和 IQueryable 执行求和?

问题描述 投票:0回答:1

我正在开发一个使用 Entity Framework Core 3.1 的项目,我需要总结候选人多年来的总经验。在我的代码中,我有一个包含 StartDate 和 EndDate 字段的 CvExperiences 表,我想计算每个候选人的总

Experience
(以年为单位)。

这是我尝试计算

Experience
的代码部分:

public class GetCandidateCVBankListQuery : DataFetchModel, IRequest<ListViewModel>
{
    public class Handler : IRequestHandler<GetCandidateCVBankListQuery, ListViewModel>
    {
        private readonly IHrmService hrmService;
        public Handler(IHrmService hrmService) => this.hrmService = hrmService;

        public async Task<ListViewModel> Handle(GetCandidateCVBankListQuery request, CancellationToken cancellationToken)
        {
            var query = hrmService.Context.CvPersonalInformations
              .Include(x => x.CvCertifications)
              .Include(x => x.CvEducations)
              .Include(x => x.CvEmergencyContacts)
              .Include(x => x.CvExperiences)
              .Include(x => x.CvSkills)
              .Include(x => x.CvReferenceDetails)
              .Include(x => x.CvProfessionalQualifications)
              .OrderByDescending(x => x.CvEducations.Any(e => e.IsHighestEducation.HasValue))
                .Select(x => new
                {
                    CandidateName = x.FullName,
                    HigherstEducation = x.CvEducations.Select(e => e.EducationLevel).FirstOrDefault(),
                    CGPA = x.CvEducations.Select(e => e.Result).FirstOrDefault(),
                    Institute = x.CvEducations.Select(e => e.InstitutionName).FirstOrDefault(),
                    Age = x.DateOfBirth.HasValue ? (DateTime.Now.Year - x.DateOfBirth.Value.Year -
                                (DateTime.Now.DayOfYear < x.DateOfBirth.Value.DayOfYear ? 1 : 0)) : (int?)null,
                    Experience = x.CvExperiences
                                .Where(e => e.StartDate.HasValue && e.EndDate.HasValue)
                                .Sum(e => (e.EndDate.Value - e.StartDate.Value).TotalDays / 365.25),
                    HomeDistrict = x.HomeDistrict
                })
              .AsQueryable();

            return await this.hrmService.GetListViewDataAsync(query, request, cancellationToken);
        }
    }
}

当我想要

Experience
结果时,这种方法不起作用,但没有
Experience
,它工作得很好。错误显示:

The LINQ expression '(EntityShaperExpression: 
    EntityType: CvExperience
    ValueBufferExpression: 
        ProjectionBindingExpression: EmptyProjectionMember
    IsNullable: False
.EndDate.Value - EntityShaperExpression: 
    EntityType: CvExperience
    ValueBufferExpression: 
        ProjectionBindingExpression: EmptyProjectionMember
    IsNullable: False
.StartDate.Value).TotalDays / 365.25' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.The LINQ expression '(EntityShaperExpression: 
    EntityType: CvExperience
    ValueBufferExpression: 
        ProjectionBindingExpression: EmptyProjectionMember
    IsNullable: False
.EndDate.Value - EntityShaperExpression: 
    EntityType: CvExperience
    ValueBufferExpression: 
        ProjectionBindingExpression: EmptyProjectionMember
    IsNullable: False
.StartDate.Value).TotalDays / 365.25' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

这里说的是LINQ不能直接翻译成SQL。我该怎么做?

c# asp.net-core
1个回答
0
投票

您可以翻译Sql server中的内置函数(DATEDIFF)

Experience = x.CvExperiences
    .Where(e => e.StartDate.HasValue && e.EndDate.HasValue)
    .Sum(e => 
        EF.Functions.DateDiffDay(e.StartDate.Value, e.EndDate.Value) / 365.0
    ) 

EF Core 将其转换为 DATEDIFF(day, StartDate, EndDate)

然后除以 365.0 即可得到近似年份

因为 Core 3.1 无法将 C# 计算的天数差异转换为 SQL。

© www.soinside.com 2019 - 2024. All rights reserved.