简体   繁体   中英

EF Core, Left Outer Join With Or Condition

I want to write a EF query for SQL like this

select *
from Table1 t1
left outer join t2 on (t1.id = t2.ParentId or t1.id2 = t2.ParentId2) 

So that I return ALL t1 rows with a match on either condition on t2, but return t1 if neither condition matches. If it was an AND condition, EF can support this, but for OR most people do it in the Where clause rather than the Join condition. However if I do that, only the matched rows are returned, not the non matched rows in t1

Eg As an AND condition its easy to do

   var result = from t1 in db.Table1s
                join t2 in db.Table2s on new {t1.id, t1.id2} equals new {t2.parentId, t2.parentId2}
                     into t2join
                from t2 in t2join.DefaultIfEmpty() 

For illustration this can be written as a cross join but does not return the t1 rows with no match

   var result = from t1 in db.Table1s
                from t2 in db.Table2s
                where t1.id == t2.parentId || t1.id2 == t2.parentId2 || t}

So I need to use the first syntax, but how can I do that with an OR clause? So Ideally I want something like

 var result = from t1 in db.Table1s
                join t2 in db.Table2s on t1.id == t2.parentId || t1.id2 == t2.parentId2 
                     into t2join
                from t2 in t2join.DefaultIfEmpty() 

I see no way of achieving this with a normal LINQ to SQL query (happy to be proven wrong). The only way round it I see is to call the direct SQL from EF and this is how I achieved that using FromSqlInterpolated

First I need a new EF model to hold my result set, but I don't want a new table for this. This is done by creating a DbSet for the ResultModel in my DbContext and then specified in the OnModelCreating, that it HasNoKey, and also map it to a null view, so not to create the table.

 public DbSet<ResultModel> ResultModelSet{ get; set; }

 protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);     

            modelBuilder.Entity<ResultModel>().HasNoKey().ToView(null);
        }

Then in my query I can run the raw sql and map it back into this model

  var result= await db.ResultModelSet
                .FromSqlInterpolated($@"select t1.id, t1.ida, t2.ParentId, t2.ParentId2
                                     from Table1 t1
                                     left outer join t2 on 
                                             (t1.id = t2.ParentId or 
                                              t1.id2 = t2.ParentId2)
                                        ")
                .ToListAsync();

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