JOIN and LEFT JOIN equivalent in LINQ

后端 未结 3 1223
长情又很酷
长情又很酷 2020-12-29 15:15

I am working with the following SQL query:

SELECT 
a.AppointmentId,
a.Status,
a.Type,
a.Title,
b.Days,
d.Description,
e.FormId
FROM Appointment a (nolock)
LE         


        
3条回答
  •  暖寄归人
    2020-12-29 15:46

    SELECT A.X, B.Y
    FROM A JOIN B ON A.X = B.Y
    

    This linq method call (to Join) will generate the above Join.

    var query = A.Join
    (
      B,
      a => a.x,
      b => b.y,
      (a, b) => new {a.x, b.y} //if you want more columns - add them here.
    );
    

    SELECT A.X, B.Y
    FROM A LEFT JOIN B ON A.X = B.Y
    

    These linq method calls (to GroupJoin, SelectMany, DefaultIfEmpty) will produce the above Left Join

    var query = A.GroupJoin
    (
      B,
      a => a.x,
      b => b.y,
      (a, g) => new {a, g}
    ).SelectMany
    (
      z => z.g.DefaultIfEmpty(),
      (z, b) =>
        new  { x = z.a.x, y = b.y } //if you want more columns - add them here.
    );
    

    The key concept here is that Linq's methods produce hierarchically shaped results, not flattened row-column shapes.

    • Linq's GroupBy produces results shaped in a hierarchy with a grouping key matched to a collection of elements (which may not be empty). SQL's GroupBy clause produces a grouping key with aggregated values - there is no sub-collection to work with.
    • Similarly, Linq's GroupJoin produces a hierarchical shape - a parent record matched to a collection of child records (which may be empty). Sql's LEFT JOIN produces a parent record matched to each child record, or a null child record if there are no other matches. To get to Sql's shape from Linq's shape, one must unpack the collection of child records with SelectMany - and deal with empty collections of child records using DefaultIfEmpty.

    And here's my attempt at linquifying that sql in the question:

    var query =
      from a in Appointment
      where a.RowStatus == 1
      where a.Type == 1
      from b in a.AppointmentFormula.Where(af => af.RowStatus == 1).DefaultIfEmpty()
      from d in a.TypeRecord //a has a type column and is related to a table named type, disambiguate the names
      from e in a.AppointmentForm.DefaultIfEmpty()
      order by a.Type
      select new { a.AppointmentId, a.Status, a.Type, a.Title, b.Days, d.Description, e.Form }
    

提交回复
热议问题