如何将给定的 lambda 查询转换为 IQueryable

How to convert given lambda query to IQueryable

我准备了这个 Linq-to-SQL 查询,它需要作为 IQueryable 执行,但它失败了。

当我通过调用 ToList 转换 filteredResult 时,效果很好,但我需要将 filteredResult 用作 IQueryable 并获得 select 结果以下。但是我得到一个错误

A lambda expression with a statement body cannot be converted to an expression tree

通过了下面的 link,但是,下面的查询如何转换为 IQueryable。根据 link,我是否需要编写 Func<object,object> 或任何转换查询的示例真的很有帮助。

"A lambda expression with a statement body cannot be converted to an expression tree"

var result = filteredResult.Select(g => {
    var type1 = g.FirstOrDefault(x => x.CategoryId == (int)CategoryEnum.Typ1);
    var type2 = g.FirstOrDefault(x => x.CategoryId == (int)CategoryEnum.Typ2);

return new AutoDetailDto
    {
        MilestoneId = g.Key.MilestoneId,
        MilestoneName = g.Key.MilestoneName,
        PGrade = type1?.GDR,
        PGradeChange = type1?.HighestGDR
        QGrade = type2.GDR,
        QGradeChange = type2?.HighestGDR    
    };
});

单独的函数无济于事。无论哪种情况,系统都无法计算出如何从复杂的 C# 代码生成 SQL。

试试这个:

// This is converted to SQl because the lambda, though compe, is a single statement
var dataResult = filteredResult.Select(g => new {
    type1 = g.FirstOrDefault(x => x.CategoryId == (int)CategoryEnum.Typ1),
    type2 = g.FirstOrDefault(x => x.CategoryId == (int)CategoryEnum.Typ2),
    MilestoneId  = g.Key.MilestoneId,
    MilestoneName = g.Key.MilestoneName
}).ToArray(); // ToArray() forces execution of the query  

// This select is done entirely in memory
var result = dataResult.Select (e =>
       new AutoDetailDto
       {
           MilestoneId = e.MilestoneId,
           MilestoneName = e.MilestoneName,
           PGrade = e.type1?.GDR,
           PGradeChange = e.type1?.HighestGDR
           QGrade = e.type2.GDR,
           QGradeChange = e.type2?.HighestGDR    
       });

我认为这应该可行。让我知道。

编辑:

奇怪的是,虽然不允许使用空传播运算符,但旧的条件 if 是允许的,所以请尝试:

var dataResult = filteredResult.Select(g => new {
        type1 = g.FirstOrDefault(x => x.CategoryId == (int)CategoryEnum.Typ1),
        type2 = g.FirstOrDefault(x => x.CategoryId == (int)CategoryEnum.Typ2),
        MilestoneId  = g.Key.MilestoneId,
        MilestoneName = g.Key.MilestoneName
    }); // No forcing of execution here

var result = dataResult.Select (e =>
       new AutoDetailDto
       {
           MilestoneId = e.MilestoneId,
           MilestoneName = e.MilestoneName,
           PGrade = e.type1 == null ? null : e.type1.GDR,
           PGradeChange = e.type1 == null ? null :e.type1.HighestGDR
           QGrade = e.type2 == null ? null : e.type2.GDR,
           QGradeChange = e.type2 == null ? null : e.type2.HighestGDR    
       });