简体   繁体   中英

How to filter LINQ query based on child table column?

I am joining 2 tables using entity framework as mentioned in below code and want to filter data on the basis of child table column but when I run the code It is sending Table 2 as empty array. While debugging the code I found below error.

Error = Unable to evaluate the expression. Operation not supported. Unknown error: 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"))
    })

Something arround these lines should work.

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,
    });

As EntityFramework works with queryables it tries to construct a query out of the select, where, orderby, ... statements. However your nested select is not supported and cannot be translated to a query.

Okay, I've never tried this...so I'm not totally sure without creating a POC, which I don't have time to create at the moment...but your select should only be "one query"...not an internal query inside the first Select...so something like this (assuming you can create sub-objects with object-initializers inside a 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
        }
    });

EDIT - No Foreign Key If you don't have a foreign-key/primary-key relationship to link on, then you must completely separate your queries. To my knowledge, your first query has to completely close (eg by calling .ToList()) before EF can run a second query.

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();
}

Apparently the elements in table2 have properties Col1 and Col2. Are you certain that property Col1 is of a string type?

If not, then Col1.Equals(string) will use Object.Equals(object), which is always false, because Col1 is not a string.

The reason you made this error is because of your method of variable naming. There is no clue at all to see what kine of elements a, b, c, db are.

Because of your abstract table1 it is already difficult to see what every variable means, so let's assume that Table1 is aa table of Teachers and Table2 is a table of Students,

The GroupJoin would be much easier to read if you'd use proper variable names:

// 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"));

Result: if the Col1 of a Student is not a string, then Table2 will remain empty

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM