如何根据子表列过滤LINQ查询?

时间:2018-02-19 18:45:44

标签: c# entity-framework linq

我正在使用下面代码中提到的实体框架加入2个表,并希望在子表列的基础上过滤数据,但是当我运行代码时它将表2作为空数组发送。调试代码时我发现下面的错误。

  

错误=无法评估表达式。操作不受支持。   未知错误:0x80070057。

context.Table1
    .GroupJoin(context.Table2, a => a.id, b => b.id, (a, b) => new SampleDTO
    {
        OutletCd = a.id,
        Name = a.Name,
        AddrLine1 = a.AddrLine1,
        AddrLine2 = a.AddrLine2,
        City = a.City,
        Zip = a.Zip,
        StateCd = a.StateCd,
        CtryCd = a.CtryCd,
        Country = a.Country,
        Phone = a.Phone,
        Table2 = b.Select(bd => new SampleDetails { Col1 = bd.Col1, Col2 = bd.Col2 })
            .Where(c => c.Col1.Equals("ABC"))
    })

3 个答案:

答案 0 :(得分:1)

这些线条周围应该有效。

context.Table1
    .Join(Table2, a => a.id, b => b.id, (a, b) => {Table1 = a, Table2 = b})
    .Where(ab => ab.Table2.Col1.Equals("ABC"))
    .Select(ab => {
        OutletCd = ab.Table1.id,
        Name = ab.Table1.Name,
        AddrLine1 = ab.Table1.AddrLine1,
        AddrLine2 = ab.Table1.AddrLine2,
        City = ab.Table1.City,
        Zip = ab.Table1.Zip,
        StateCd = ab.Table1.StateCd,
        CtryCd = ab.Table1.CtryCd,
        Country = ab.Table1.Country,
        Phone = ab.Table1.Phone,
    });

当EntityFramework与queryables一起使用时,它会尝试从select,where,orderby,...语句中构造一个查询。但是,您的嵌套选择不受支持,无法转换为查询。

答案 1 :(得分:1)

好吧,我从来没有尝试过这个......所以我没有完全确定没有创建POC,我现在没有时间创作......但是你的选择应该只是"一个查询" ...不是第一个Select中的内部查询......所以这样的事情(假设你可以在Select中创建带有对象初始化器的子对象:

var result = context.Table1.Include( a => a.b )
    .Where( a => a.b.Col1.Equals("ABC")
    .Select( x => new SampleDto {
        OutletCd = a.id,
        //other cols
        Table2 = new SampleDetails {
            Col1 = b.Col1,
            Col2 = b.Col2
        }
    });

编辑 - 没有外键 如果您没有链接的外键/主键关系,则必须完全分离查询。据我所知,您的第一个查询必须完全关闭(例如通过调用.ToList()),然后EF才能运行第二个查询。

var results = context.Table1
    .Where( a => a.b.Col1.Equals("ABC")
    .Select( x => new SampleDto {
        OutletCd = a.id,
        //other cols
    })
    .ToList();

foreach( var sampleDto in results ) {
    sampleDto.Table2 = context.Table2.Where( x => x.Condition ).ToList();
}

答案 2 :(得分:1)

显然,table2中的元素具有属性Col1和Col2。您确定属性Col1是字符串类型吗?

如果没有,那么Col1.Equals(string)将使用Object.Equals(object),它始终为false,因为Col1不是字符串。

您犯此错误的原因是您的变量命名方法。根本没有任何线索可以看出元素a,b,c,db是什么。

由于你的抽象table1已经很难看出每个变量的含义,所以让我们假设Table1是一个教师表,Table2是一个学生表,

如果你使用适当的变量名,GroupJoin会更容易阅读:

// groupjoin teachers and students:
var result = context.Teachers.GroupJoin(context.Students, 
    teacher => teacher.Id,             // from each Teacher take the Id
    student => student.TeacherId,      // from each Student take the teacherId

    // when they match, group the teacher and all his matching students:
    (teacher, students) => new 
    {                          // make a new object:
                               // get some Teacher properties
         Name = Teacher.Name,
         AddrLine1 = Teacher.AddrLine1,
         ...

         // make a table from the columns from all the Teacher's students:
         Table2 = students 
            .Select(student => new
            {
                Col1 = student.Col1,
                Col2 = student.Col2,
            })      
            // here it is clearly to see that Col1 comes from Student
            // I don't want all students, only those with ABC for Col1, so:
            .Where(studentColumns => studentColumns.Col1.Equals("ABC"));

结果:如果学生的Col1不是字符串,则Table2将保持为空