简体   繁体   中英

left outer join in linq error at defaultifempty

so i have 3 tables i want to do left outer join on all 3 but say

table 1 has

id   name
1    peter
2    john

table 2 has

id address
1   123 ave 
2   456 blvd

table 3 has

table1id table2id
1           1
1           2
2           1 
2           2

table 3 is a xref of table 1 and 2

so if i add one record into table 1, when i search by name, i need to get name and address that name associates with, but it returns nothing because i haven't inserted anything into table 3 yet. so i'm trying to do a left join but i run into an error

var query = from t1 in table1 
            join t3 in table3 on t1.id equals t3.table1id into leftt1 
            from l1 in leftt1.defaultifempty() 
            join t2 in table2 on l1.table2id equals t2.id 
            select.......

the error is at defaultifempty. it actually returns empty instead of the new record i just added. is there something wrong with my left outer join? please help. thanks

Thank you for clarification.

Assuming the description of issue, i think you need to use INNER JOIN instead of LEFT JOIN , because 3rd table stores data which exist in 1st and 2nd table.

See example (using LinqPad):

DataTable dt1 = new DataTable();
DataColumn dc = new DataColumn("id", System.Type.GetType("System.Int32"));
dt1.Columns.Add(dc);
dc = new DataColumn("name", System.Type.GetType("System.String"));
dt1.Columns.Add(dc);
dt1.Rows.Add(new Object[]{1, "Peter"});
dt1.Rows.Add(new Object[]{2, "John"});


DataTable dt2 = new DataTable();
dc = new DataColumn("id", System.Type.GetType("System.Int32"));
dt2.Columns.Add(dc);
dc = new DataColumn("address", System.Type.GetType("System.String"));
dt2.Columns.Add(dc);
dt2.Rows.Add(new Object[]{1, "123 ave"});
dt2.Rows.Add(new Object[]{2, "456 blvd"});

DataTable dt3 = new DataTable();
dc = new DataColumn("id1", System.Type.GetType("System.Int32"));
dt3.Columns.Add(dc);
dc = new DataColumn("id2", System.Type.GetType("System.Int32"));
dt3.Columns.Add(dc);
dt3.Rows.Add(new Object[]{1, 1});
dt3.Rows.Add(new Object[]{1, 2});
dt3.Rows.Add(new Object[]{2, 1});
dt3.Rows.Add(new Object[]{2, 2});

var qry = from refdata in dt3.AsEnumerable()
        join userdata in dt1.AsEnumerable() on refdata.Field<int>("id1") equals userdata.Field<int>("id")
        join addressdata in dt2.AsEnumerable() on refdata.Field<int>("id2") equals addressdata.Field<int>("id")
        select new
        {
            uid = userdata.Field<int>("id"),
            uname = userdata.Field<string>("name"),
            aid = addressdata.Field<int>("id"),
            aadress = addressdata.Field<string>("address")
        };

Result:

uid    uname    aid   aadress
1      Peter    1     123 ave 
1      Peter    2     456 blvd 
2      John     1     123 ave 
2      John     2     456 blvd 

i ended up having to redefined my structure after the join like this

var query = from t1 in table1 
        join t3 in table3 on t1.id equals t3.table1id into leftt1 
        from l1 in leftt1.defaultifempty(new t3 {table1id=table1id.id, table2id=0}) 
        join t2 in table2 on l1.table2id equals t2.id 
        select.......

you can do the same for the other ones as well. it is working now. thanks

You can do this:

var query = from t1 in table1s 
            join t3 in table3s on t1.Id equals t3.table1Id 
                into left1
            from l1 in left1.DefaultIfEmpty()
            join t2 in table2s on (l1 == null ? -1 : l1.table2Id) equals t2.Id
                into left2
            from l2 in left2.DefaultIfEmpty()
            select new { t1, l2 };

So you don't need a dummy t3 instance to cross the outer join gap.

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