【问题标题】:The query that works under Entity Framework 6 does not work in .Net5在 Entity Framework 6 下工作的查询在 .Net5 中不起作用
【发布时间】:2021-07-02 08:39:00
【问题描述】:

我有一个查询在 .Net5 下无法运行的问题 我不确定为什么在 Entity Framework 6 下运行良好的查询没有在 .Net5 中获得标准列表。要开始使用 Core,您需要做什么?

 var listModel =
                (
                from dane in _dbContext.Standard
                join kraj in _dbContext.CountryStandard
                on dane.IdCountryStandard equals kraj.IdCountryStandard
                join opcja in _dbContext.MeasureDiameterOption
                on dane.IdStandard equals opcja.IdStandard
                join metoda in _dbContext.MeasureDiameterMethod
                on opcja.IdMeasureDiameterMethod equals metoda.IdMeasureDiameterMethod
                join sposob in _dbContext.WalkingLineRadius
                on opcja.IdWalkingLineRadius equals sposob.IdWalkingLineRadius
                
                select new StandardEnt()
                {
                    IdStandard = dane.IdStandard,
                    IdCountryStandard = dane.IdCountryStandard,
                    StandardName = dane.StandardName,
                    IsActive = dane.IsActive,
                    NameCountry = kraj.NameCountryStandard,
                    FreeHeadSpace = (double)dane.FreeHeadSpace,
                    IsTlcStandard = dane.IsTlcStandard,
                    MinLandingSize = (double)dane.MinLandingSize,
                    MinStepHeight = (double)dane.MinStepHeight,
                    MaxStepHeight = (double)dane.MaxStepHeight,
                    MinConvinience = (double)dane.MinConvinience,
                    MaxConvinience = (double)dane.MaxConvinience,
                    MaxStepDeep = (double)dane.MaxStepDeep,
                    MinStepDeep = (double)dane.MinStepDeep,
                    MaxStepWidth = (double)dane.MaxStepWidth,
                    WidthLimit = (double)dane.WidthLimit,
                    StartOverlap = (double)dane.StartOverlap,
                    InternalHandrailMaxRadius = (double)dane.InternalHandrailMaxRadius,
                    PrimaryCalcMethod = (from metody in _dbContext.MeasureDiameterOption
                                         select new MeasureDiameterMethodEnt()
                                         {
                                             IdStandard = metody.IdStandard,
                                             IdMeasureDiameterOption = metody.IdMeasureDiameterOption,
                                             Description = metody.Description,
                                             IdMeasureDiameterMethod = metody.IdMeasureDiameterMethod,
                                             IdWalkingLineRadius = metody.IdWalkingLineRadius,
                                             IdCalcMethodType = metody.WalkingLineRadius.CalcMethodType.IdCalcMethodType,
                                             IdWalkingLineMeasure = metody.WalkingLineRadius.WalkingLineMeasure.IdWalkingLineMeasure,
                                             //CalcMethod = Enum.Parse<DiamDivide>(opcja.WalkingLineRadius.CalcMethodType.CalcMethodNameType),
                                             //WalkingLineMeasure = Enum.Parse<WalkingLineMeasureMethod>(opcja.WalkingLineRadius.WalkingLineMeasure.WalkingLineMeasureName),
                                             CalcMethodName = metody.MeasureDiameterMethod.CalcMethodName,
                                             CalcMethodNameType = metody.WalkingLineRadius.CalcMethodType.CalcMethodNameType,
                                             WalkingLineMeasureName = metody.WalkingLineRadius.WalkingLineMeasure.WalkingLineMeasureName,
                                             FirstWidth = (double)metody.WalkingLineRadius.FirstWidth,
                                             SecondWidth = (double)metody.WalkingLineRadius.SecondWidth
                                         }).Where(s => s.CalcMethodName == "PrimaryCalcMethod" && s.IdStandard == dane.IdStandard).FirstOrDefault(),
                    SecondaryCalcMethod = (from metody in _dbContext.MeasureDiameterOption
                                           select new MeasureDiameterMethodEnt()
                                           {
                                               IdStandard = metody.IdStandard,
                                               IdMeasureDiameterOption = metody.IdMeasureDiameterOption,
                                               Description = metody.Description,
                                               IdMeasureDiameterMethod = metody.IdMeasureDiameterMethod,
                                               IdWalkingLineRadius = metody.IdWalkingLineRadius,
                                               IdCalcMethodType = metody.WalkingLineRadius.CalcMethodType.IdCalcMethodType,
                                               IdWalkingLineMeasure = metody.WalkingLineRadius.WalkingLineMeasure.IdWalkingLineMeasure,
                                               //CalcMethod = Enum.Parse<DiamDivide>(opcja.WalkingLineRadius.CalcMethodType.CalcMethodNameType),
                                               //WalkingLineMeasure = Enum.Parse<WalkingLineMeasureMethod>(opcja.WalkingLineRadius.WalkingLineMeasure.WalkingLineMeasureName),
                                               CalcMethodName = metody.MeasureDiameterMethod.CalcMethodName,
                                               CalcMethodNameType = metody.WalkingLineRadius.CalcMethodType.CalcMethodNameType,
                                               WalkingLineMeasureName = metody.WalkingLineRadius.WalkingLineMeasure.WalkingLineMeasureName,
                                               FirstWidth = (double)metody.WalkingLineRadius.FirstWidth,
                                               SecondWidth = (double)metody.WalkingLineRadius.SecondWidth
                                           }).Where(s => s.CalcMethodName == "SecondaryCalcMethod" && s.IdStandard == dane.IdStandard).FirstOrDefault()
                                           
                }
            ).GroupBy(x => x.IdStandard).Select(x => x.FirstOrDefault()).ToList();
            return  listModel;

还有错误按摩。

LINQ 表达式 'GroupByShaperExpression: KeySelector: s.IdStandard, ElementSelector:new StandardEnt{ IdStandard = (int)ProjectionBindingExpression: 0, IdCountryStandard = (int)ProjectionBindingExpression: 1, StandardName = ProjectionBindingExpression:2,IsActive = (bool)ProjectionBindingExpression: 3, NameCountry = ProjectionBindingExpression: 4, FreeHeadSpace = (double)ProjectionBindingExpression: 5, IsTlcStandard = (bool)ProjectionBindingExpression: 6, MinLandingSize = (double)ProjectionBindingExpression: 7, MinStepHeight = (double)ProjectionBindingExpression: 8, MaxStepHeight = (double)ProjectionBindingExpression: 9, MinConvinience = (double)ProjectionBindingExpression: 10, MaxConvinience = (double)ProjectionBindingExpression: 11, MaxStepDeep = ProjectionBindingExpression:12,MinStepDeep = ProjectionBindingExpression:13,MaxStepWidth = ProjectionBindingExpression: 14, WidthLimit = ProjectionBindingExpression:15,StartOverlap = (double)ProjectionBindingExpression: 16, InternalHandrailMaxRadius = ProjectionBindingExpression:17,PrimaryCalcMethod = ProjectionBindingExpression: 30 == default(Nullable) ? 默认(MeasureDiameterMethodEnt):新的MeasureDiameterMethodEnt{ IdStandard = ProjectionBindingExpression:18,IdMeasureDiameterOption = (int)ProjectionBindingExpression: 19, 描述 = ProjectionBindingExpression: 20, IdMeasureDiameterMethod = (int)ProjectionBindingExpression: 21, IdWalkingLineRadius = (int)ProjectionBindingExpression: 22, IdCalcMethodType = (int)ProjectionBindingExpression: 23, IdWalkingLineMeasure = (int)ProjectionBindingExpression: 24, CalcMethodName = ProjectionBindingExpression:25,CalcMethodNameType = ProjectionBindingExpression:26,WalkingLineMeasureName = ProjectionBindingExpression:27,FirstWidth = (double)ProjectionBindingExpression: 28, SecondWidth = (double)ProjectionBindingExpression: 29 } , SecondaryCalcMethod = ProjectionBindingExpression: 43 == default(Nullable) ? 默认(MeasureDiameterMethodEnt):新的MeasureDiameterMethodEnt{ IdStandard = ProjectionBindingExpression:31,IdMeasureDiameterOption = (int)ProjectionBindingExpression: 32, 描述 = ProjectionBindingExpression: 33, IdMeasureDiameterMethod = (int)ProjectionBindingExpression: 34, IdWalkingLineRadius = (int)ProjectionBindingExpression: 35, IdCalcMethodType = (int)ProjectionBindingExpression: 36, IdWalkingLineMeasure = (int)ProjectionBindingExpression: 37, CalcMethodName = ProjectionBindingExpression:38,CalcMethodNameType = ProjectionBindingExpression:39,WalkingLineMeasureName = ProjectionBindingExpression:40,FirstWidth = (double)ProjectionBindingExpression: 41, SecondWidth = (double)ProjectionBindingExpression: 42 } } .FirstOrDefault()' 可以 不被翻译。要么重写查询形式, 翻译,或通过插入显式切换到客户端评估 调用“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或 'ToListAsync'。见https://go.microsoft.com/fwlink/?linkid=2101038 更多信息。

【问题讨论】:

  • 我在项目中使用.NET5
  • 如果您将子查询PrimaryCalcMethodSecondaryCalcMethod 分成单独的表达式,那么它应该会更容易调试。在查询末尾的 group-by 方法中引用 s.IdStandard 时,应该更容易识别出问题所在。此外,为了理解,完全用查询语法或完全用方法语法重写查询可能更容易。
  • @GSerg EF6 有客户端评估吗?
  • 更好的选择是用导航属性替换所有连接和子查询。然后查询看起来就没有那么令人印象深刻了,而且最好的部分是它不需要分组。

标签: c# linq asp.net-core entity-framework-core .net-5


【解决方案1】:

这里的问题是在GroupBy 之后您无法访问分组项目。只有键和聚合结果可用。这是严格的 SQL 限制,在翻译 LINQ 查询时没有涵盖所有情况的灵丹妙药。

我已将您的查询重构为可翻译,但这是一种解决方法,因为 SQL Server 必须进行更多计算。

投影辅助方法:

public static IQueryable<MeasureDiameterMethodEnt> Project(IQueryable<MeasureDiameterOption> query)
{
    return query.Select(metody => new MeasureDiameterMethodEnt
        {
            IdStandard = metody.IdStandard,
            IdMeasureDiameterOption = metody.IdMeasureDiameterOption,
            Description = metody.Description,
            IdMeasureDiameterMethod = metody.IdMeasureDiameterMethod,
            IdWalkingLineRadius = metody.IdWalkingLineRadius,
            IdCalcMethodType = metody.WalkingLineRadius.CalcMethodType.IdCalcMethodType,
            IdWalkingLineMeasure = metody.WalkingLineRadius.WalkingLineMeasure.IdWalkingLineMeasure,
            //CalcMethod = Enum.Parse<DiamDivide>(opcja.WalkingLineRadius.CalcMethodType.CalcMethodNameType),
            //WalkingLineMeasure = Enum.Parse<WalkingLineMeasureMethod>(opcja.WalkingLineRadius.WalkingLineMeasure.WalkingLineMeasureName),
            CalcMethodName = metody.MeasureDiameterMethod.CalcMethodName,
            CalcMethodNameType = metody.WalkingLineRadius.CalcMethodType.CalcMethodNameType,
            WalkingLineMeasureName = metody.WalkingLineRadius.WalkingLineMeasure.WalkingLineMeasureName,
            FirstWidth = (double)metody.WalkingLineRadius.FirstWidth,
            SecondWidth = (double)metody.WalkingLineRadius.SecondWidth
        }
    );
}

最后的查询:

var notGrouped =
    from dane in _dbContext.Standard
    join kraj in _dbContext.CountryStandard
    on dane.IdCountryStandard equals kraj.IdCountryStandard
    join opcja in _dbContext.MeasureDiameterOption
    on dane.IdStandard equals opcja.IdStandard
    join metoda in _dbContext.MeasureDiameterMethod
    on opcja.IdMeasureDiameterMethod equals metoda.IdMeasureDiameterMethod
    join sposob in _dbContext.WalkingLineRadius
    on opcja.IdWalkingLineRadius equals sposob.IdWalkingLineRadius
    
    select new
    {
        IdStandard = dane.IdStandard,
        IdCountryStandard = dane.IdCountryStandard,
        StandardName = dane.StandardName,
        IsActive = dane.IsActive,
        NameCountry = kraj.NameCountryStandard,
        FreeHeadSpace = (double)dane.FreeHeadSpace,
        IsTlcStandard = dane.IsTlcStandard,
        MinLandingSize = (double)dane.MinLandingSize,
        MinStepHeight = (double)dane.MinStepHeight,
        MaxStepHeight = (double)dane.MaxStepHeight,
        MinConvinience = (double)dane.MinConvinience,
        MaxConvinience = (double)dane.MaxConvinience,
        MaxStepDeep = (double)dane.MaxStepDeep,
        MinStepDeep = (double)dane.MinStepDeep,
        MaxStepWidth = (double)dane.MaxStepWidth,
        WidthLimit = (double)dane.WidthLimit,
        StartOverlap = (double)dane.StartOverlap,
        InternalHandrailMaxRadius = (double)dane.InternalHandrailMaxRadius                                
    };

var firstEntryQuery = 
    from u in notGrouped.Select(x => new { x.IdStandard }).Distinct()
    from q in notGrouped.Where(q => q.IdStandard == u.IdStandard).Take(1)
    from primary in Project(_dbContext.MeasureDiameterOption)
        .Where(s => s.CalcMethodName == "PrimaryCalcMethod" && s.IdStandard == q.IdStandard)
        .Take(1)
        .DefaultIfempty()
    from secondary in Project(_dbContext.MeasureDiameterOption)
        .Where(s => s.CalcMethodName == "SecondaryCalcMethod" && s.IdStandard == q.IdStandard)
        .Take(1)
        .DefaultIfempty()
    select new StandardEnt
    {
        IdStandard = q.IdStandard,
        IdCountryStandard = q.IdCountryStandard,
        StandardName = q.StandardName,
        IsActive = q.IsActive,
        NameCountry = q.NameCountry,
        FreeHeadSpace = q.FreeHeadSpace,
        IsTlcStandard = q.IsTlcStandard,
        MinLandingSize = q.MinLandingSize,
        MinStepHeight = q.MinStepHeight,
        MaxStepHeight = q.MaxStepHeight,
        MinConvinience = q.MinConvinience,
        MaxConvinience = q.MaxConvinience,
        MaxStepDeep = q.MaxStepDeep,
        MinStepDeep = q.MinStepDeep,
        MaxStepWidth = q.MaxStepWidth,
        WidthLimit = q.WidthLimit,
        StartOverlap = q.StartOverlap,
        InternalHandrailMaxRadius = q.InternalHandrailMaxRadius,

        PrimaryCalcMethod = primary,
        SecondaryCalcMethod = secondary             
    };

【讨论】:

    猜你喜欢
    • 2014-03-15
    • 2015-11-09
    • 2020-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-07
    相关资源
    最近更新 更多