首页 文章

LINQ中的LEFT OUTER JOIN

提问于
浏览
404

如何在不使用 join-on-equals-into 子句的情况下在C#LINQ中对对象执行左外连接?用 where 子句有没有办法做到这一点?正确的问题:对于内连接很容易,我有这样的解决方案

List<JoinPair> innerFinal = (from l in lefts from r in rights where l.Key == r.Key
                             select new JoinPair { LeftId = l.Id, RightId = r.Id})

但对于左外连接我需要一个解决方案 . 我是这样的,但它不起作用

List< JoinPair> leftFinal = (from l in lefts from r in rights
                             select new JoinPair { 
                                            LeftId = l.Id, 
                                            RightId = ((l.Key==r.Key) ? r.Id : 0
                                        })

JoinPair是一个类:

public class JoinPair { long leftId; long rightId; }

19 回答

  • 1

    这是与LINQ比较的SQL语法内外连接的语法 . 左外连接:

    http://www.ozkary.com/2011/07/linq-to-entity-inner-and-left-joins.html

    “以下示例在产品和类别之间进行组连接 . 这实际上是左连接 . 即使类别表为空,into表达式也会返回数据 . 要访问类别表的属性,我们现在必须从可枚举的结果中进行选择通过在catList.DefaultIfEmpty()语句中添加from cl .

  • 7

    LEFT OUTER JOIN 的简单解决方案:

    var setA = context.SetA;
    var setB = context.SetB.Select(st=>st.Id).Distinct().ToList();
    var leftOuter  = setA.Where(stA=> !setB.Contains(stA.Id));
    

    notes

    • 要提高性能,可以将SetB转换为 Dictionary (如果已完成,则必须更改此项: !setB.Contains(stA.Id) )或 HashSet

    • 当涉及多个字段时,可以使用 Set 操作和实现的类来实现: IEqualityComparer

  • 486

    看看这个example . 此查询应该有效:

    var leftFinal = from left in lefts
                    join right in rights on left equals right.Left into leftRights
                    from leftRight in leftRights.DefaultIfEmpty()
                    select new { LeftId = left.Id, RightId = left.Key==leftRight.Key ? leftRight.Id : 0 };
    
  • 2

    有三个表格:人员,学校和人员学校,它们将人们与他们所在的学校联系起来 . 在表人员学校中没有提到id = 6的人 . 但是,id = 6的人在结果lef-joined网格中显示 .

    List<Person> persons = new List<Person>
    {
        new Person { id = 1, name = "Alex", phone = "4235234" },
        new Person { id = 2, name = "Bob", phone = "0014352" },
        new Person { id = 3, name = "Sam", phone = "1345" },
        new Person { id = 4, name = "Den", phone = "3453452" },
        new Person { id = 5, name = "Alen", phone = "0353012" },
        new Person { id = 6, name = "Simon", phone = "0353012" }
    };
    
    List<School> schools = new List<School>
    {
        new School { id = 1, name = "Saint. John's school"},
        new School { id = 2, name = "Public School 200"},
        new School { id = 3, name = "Public School 203"}
    };
    
    List<PersonSchool> persons_schools = new List<PersonSchool>
    {
        new PersonSchool{id_person = 1, id_school = 1},
        new PersonSchool{id_person = 2, id_school = 2},
        new PersonSchool{id_person = 3, id_school = 3},
        new PersonSchool{id_person = 4, id_school = 1},
        new PersonSchool{id_person = 5, id_school = 2}
        //a relation to the person with id=6 is absent
    };
    
    var query = from person in persons
                join person_school in persons_schools on person.id equals person_school.id_person
                into persons_schools_joined
                from person_school_joined in persons_schools_joined.DefaultIfEmpty()
                from school in schools.Where(var_school => person_school_joined == null ? false : var_school.id == person_school_joined.id_school).DefaultIfEmpty()
                select new { Person = person.name, School = school == null ? String.Empty : school.name };
    
    foreach (var elem in query)
    {
        System.Console.WriteLine("{0},{1}", elem.Person, elem.School);
    }
    
  • 27

    使用lambda表达式

    db.Categories    
      .GroupJoin(
          db.Products,
          Category => Category.CategoryId,
          Product => Product.CategoryId,
          (x, y) => new { Category = x, Products = y })
      .SelectMany(
          xy => xy.Products.DefaultIfEmpty(),
          (x, y) => new { Category = x.Category, Product = y })
      .Select(s => new
      {
          CategoryName = s.Category.Name,     
          ProductName = s.Product.Name   
      })
    
  • 1

    通过扩展方法实现左外连接可能看起来像

    public static IEnumerable<Result> LeftJoin<TOuter, TInner, TKey, Result>(
      this IEnumerable<TOuter> outer, IEnumerable<TInner> inner
      , Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector
      , Func<TOuter, TInner, Result> resultSelector, IEqualityComparer<TKey> comparer)
      {
        if (outer == null)
          throw new ArgumentException("outer");
    
        if (inner == null)
          throw new ArgumentException("inner");
    
        if (outerKeySelector == null)
          throw new ArgumentException("outerKeySelector");
    
        if (innerKeySelector == null)
          throw new ArgumentException("innerKeySelector");
    
        if (resultSelector == null)
          throw new ArgumentException("resultSelector");
    
        return LeftJoinImpl(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer ?? EqualityComparer<TKey>.Default);
      }
    
      static IEnumerable<Result> LeftJoinImpl<TOuter, TInner, TKey, Result>(
          IEnumerable<TOuter> outer, IEnumerable<TInner> inner
          , Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector
          , Func<TOuter, TInner, Result> resultSelector, IEqualityComparer<TKey> comparer)
      {
        var innerLookup = inner.ToLookup(innerKeySelector, comparer);
    
        foreach (var outerElment in outer)
        {
          var outerKey = outerKeySelector(outerElment);
          var innerElements = innerLookup[outerKey];
    
          if (innerElements.Any())
            foreach (var innerElement in innerElements)
              yield return resultSelector(outerElment, innerElement);
          else
            yield return resultSelector(outerElment, default(TInner));
         }
       }
    

    然后resultselector必须处理null元素 . FX .

    static void Main(string[] args)
       {
         var inner = new[] { Tuple.Create(1, "1"), Tuple.Create(2, "2"), Tuple.Create(3, "3") };
         var outer = new[] { Tuple.Create(1, "11"), Tuple.Create(2, "22") };
    
         var res = outer.LeftJoin(inner, item => item.Item1, item => item.Item1, (it1, it2) =>
         new { Key = it1.Item1, V1 = it1.Item2, V2 = it2 != null ? it2.Item2 : default(string) });
    
         foreach (var item in res)
           Console.WriteLine(string.Format("{0}, {1}, {2}", item.Key, item.V1, item.V2));
       }
    
  • 9

    Necromancing .
    如果使用数据库驱动的LINQ提供程序,则可以如下编写更易读的左外连接:

    from maintable in Repo.T_Whatever 
    from xxx in Repo.T_ANY_TABLE.Where(join condition).DefaultIfEmpty()
    

    如果省略 DefaultIfEmpty() ,则会有内连接 .

    接受接受的答案:

    from c in categories
        join p in products on c equals p.Category into ps
        from p in ps.DefaultIfEmpty()
    

    这种语法非常混乱,当你想要离开连接MULTIPLE表时,它是如何工作的还不清楚 .

    Note
    应该注意的是 from alias in Repo.whatever.Where(condition).DefaultIfEmpty() 与外部应用/左连接 - 横向相同,任何(体面的)数据库优化器完全能够转换为左连接,只要你不在Linq中执行此操作即可 . -2对象(因为在使用Linq-to-Objects时没有DB优化器) .

    Detailed Example

    var query2 = (
        from users in Repo.T_User
        from mappings in Repo.T_User_Group
             .Where(mapping => mapping.USRGRP_USR == users.USR_ID)
             .DefaultIfEmpty() // <== makes join left join
        from groups in Repo.T_Group
             .Where(gruppe => gruppe.GRP_ID == mappings.USRGRP_GRP)
             .DefaultIfEmpty() // <== makes join left join
    
        // where users.USR_Name.Contains(keyword)
        // || mappings.USRGRP_USR.Equals(666)  
        // || mappings.USRGRP_USR == 666 
        // || groups.Name.Contains(keyword)
    
        select new
        {
             UserId = users.USR_ID
            ,UserName = users.USR_User
            ,UserGroupId = groups.ID
            ,GroupName = groups.Name
        }
    
    );
    
    
    var xy = (query2).ToList();
    

    当与LINQ 2 SQL一起使用时,它将很好地转换为以下非常清晰的SQL查询:

    SELECT 
         users.USR_ID AS UserId 
        ,users.USR_User AS UserName 
        ,groups.ID AS UserGroupId 
        ,groups.Name AS GroupName 
    FROM T_User AS users
    
    LEFT JOIN T_User_Group AS mappings
       ON mappings.USRGRP_USR = users.USR_ID
    
    LEFT JOIN T_Group AS groups
        ON groups.GRP_ID == mappings.USRGRP_GRP
    

    Edit:

    有关更复杂的示例,另请参阅“Convert SQL Server query to Linq query” .

    另外,如果你在Linq-2-Objects(而不是Linq-2-SQL)中进行它,你应该采用老式的方式(因为LINQ to SQL正确地将它转换为连接操作,但是对于这个方法的对象)强制完全扫描,并没有利用索引搜索,为什么...):

    var query2 = (
        from users in Repo.T_Benutzer
        join mappings in Repo.T_Benutzer_Benutzergruppen on mappings.BEBG_BE equals users.BE_ID into tmpMapp
        join groups in Repo.T_Benutzergruppen on groups.ID equals mappings.BEBG_BG into tmpGroups
        from mappings in tmpMapp.DefaultIfEmpty()
        from groups in tmpGroups.DefaultIfEmpty()
        select new
        {
             UserId = users.BE_ID
            ,UserName = users.BE_User
            ,UserGroupId = mappings.BEBG_BG
            ,GroupName = groups.Name
        }
    
    );
    
  • 0

    这是一般形式(已在其他答案中提供)

    var c =
        from a in alpha
        join b in beta on b.field1 equals a.field1 into b_temp
        from b_value in b_temp.DefaultIfEmpty()
        select new { Alpha = a, Beta = b_value };
    

    不过这里有一个解释,我希望能澄清这实际意味着什么!

    join b in beta on b.field1 equals a.field1 into b_temp
    

    实际上创建了一个单独的结果集b_temp,它有效地包含右侧条目的空“行”(“b”中的条目) .

    然后是下一行:

    from b_value in b_temp.DefaultIfEmpty()
    

    ..对结果集进行设置,在右侧设置'row'的默认空值,并将右侧行连接的结果设置为'b_value'的值(即右边的值)手边,如果有匹配的记录,或者'null',如果没有) .

    现在,如果右侧是单独的LINQ查询的结果,它将由匿名类型组成,它们只能是“某事”或“空” . 如果它是一个可枚举的(例如一个List - 其中MyObjectB是一个有2个字段的类),那么就可以具体说明默认的'null'值用于它的属性:

    var c =
        from a in alpha
        join b in beta on b.field1 equals a.field1 into b_temp
        from b_value in b_temp.DefaultIfEmpty( new MyObjectB { Field1 = String.Empty, Field2 = (DateTime?) null })
        select new { Alpha = a, Beta_field1 = b_value.Field1, Beta_field2 = b_value.Field2 };
    

    这确保'b'本身不为null(但是它的属性可以为null,使用您指定的默认空值),这允许您检查b_value的属性而不会获得b_value的空引用异常 . 请注意,对于可为空的DateTime,必须在“DefaultIfEmpty”的规范中将(DateTime?)的类型(即“可空的DateTime”)指定为null的“Type”(这也适用于非本机的类型) '可空,例如双,漂浮) .

    您只需链接上述语法即可执行多个左外连接 .

  • 98

    在linq中执行左外连接C#//执行左外连接

    class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
    
    class Child
    {
        public string Name { get; set; }
        public Person Owner { get; set; }
    }
    public class JoinTest
    {
        public static void LeftOuterJoinExample()
        {
            Person magnus = new Person { FirstName = "Magnus", LastName = "Hedlund" };
            Person terry = new Person { FirstName = "Terry", LastName = "Adams" };
            Person charlotte = new Person { FirstName = "Charlotte", LastName = "Weiss" };
            Person arlene = new Person { FirstName = "Arlene", LastName = "Huff" };
    
            Child barley = new Child { Name = "Barley", Owner = terry };
            Child boots = new Child { Name = "Boots", Owner = terry };
            Child whiskers = new Child { Name = "Whiskers", Owner = charlotte };
            Child bluemoon = new Child { Name = "Blue Moon", Owner = terry };
            Child daisy = new Child { Name = "Daisy", Owner = magnus };
    
            // Create two lists.
            List<Person> people = new List<Person> { magnus, terry, charlotte, arlene };
            List<Child> childs = new List<Child> { barley, boots, whiskers, bluemoon, daisy };
    
            var query = from person in people
                        join child in childs
                        on person equals child.Owner into gj
                        from subpet in gj.DefaultIfEmpty()
                        select new
                        {
                            person.FirstName,
                            ChildName = subpet!=null? subpet.Name:"No Child"
                        };
                           // PetName = subpet?.Name ?? String.Empty };
    
            foreach (var v in query)
            {
                Console.WriteLine($"{v.FirstName + ":",-25}{v.ChildName}");
            }
        }
    
        // This code produces the following output:
        //
        // Magnus:        Daisy
        // Terry:         Barley
        // Terry:         Boots
        // Terry:         Blue Moon
        // Charlotte:     Whiskers
        // Arlene:        No Child
    

    https://dotnetwithhamid.blogspot.in/

  • 15

    如果您需要加入并过滤某些内容,可以在联接之外完成 . 可以在创建集合后完成过滤 .

    在这种情况下,如果我在连接条件中执行此操作,我会减少返回的行 .

    使用三元条件 (= n == null ? "__" : n.MonDayNote,)

    • 如果对象是 null (因此不匹配),则返回 ? 之后的内容 . __ ,在这种情况下 .

    • 否则,返回 : 之后的内容, n.MonDayNote .

    感谢其他贡献者,我从自己的问题开始 .


    var schedLocations = (from f in db.RAMS_REVENUE_LOCATIONS
                  join n in db.RAMS_LOCATION_PLANNED_MANNING on f.revenueCenterID equals
    
                      n.revenueCenterID into lm
    
                  from n in lm.DefaultIfEmpty()
    
                  join r in db.RAMS_LOCATION_SCHED_NOTE on f.revenueCenterID equals r.revenueCenterID
                  into locnotes
    
                  from r in locnotes.DefaultIfEmpty()
                  where f.LocID == nLocID && f.In_Use == true && f.revenueCenterID > 1000
    
                  orderby f.Areano ascending, f.Locname ascending
                  select new
                  {
                      Facname = f.Locname,
                      f.Areano,
                      f.revenueCenterID,
                      f.Locabbrev,
    
                      //  MonNote = n == null ? "__" : n.MonDayNote,
                      MonNote = n == null ? "__" : n.MonDayNote,
                      TueNote = n == null ? "__" : n.TueDayNote,
                      WedNote = n == null ? "__" : n.WedDayNote,
                      ThuNote = n == null ? "__" : n.ThuDayNote,
    
                      FriNote = n == null ? "__" : n.FriDayNote,
                      SatNote = n == null ? "__" : n.SatDayNote,
                      SunNote = n == null ? "__" : n.SunDayNote,
                      MonEmpNbr = n == null ? 0 : n.MonEmpNbr,
                      TueEmpNbr = n == null ? 0 : n.TueEmpNbr,
                      WedEmpNbr = n == null ? 0 : n.WedEmpNbr,
                      ThuEmpNbr = n == null ? 0 : n.ThuEmpNbr,
                      FriEmpNbr = n == null ? 0 : n.FriEmpNbr,
                      SatEmpNbr = n == null ? 0 : n.SatEmpNbr,
                      SunEmpNbr = n == null ? 0 : n.SunEmpNbr,
                      SchedMondayDate = n == null ? dMon : n.MondaySchedDate,
                      LocNotes = r == null ? "Notes: N/A" : r.LocationNote
    
                  }).ToList();
                    Func<int, string> LambdaManning = (x) => { return x == 0 ? "" : "Manning:" + x.ToString(); };
            DataTable dt_ScheduleMaster = PsuedoSchedule.Tables["ScheduleMasterWithNotes"];
            var schedLocations2 = schedLocations.Where(x => x.SchedMondayDate == dMon);
    
  • 1

    看看这个例子

    class Person
    {
        public int ID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Phone { get; set; }
    }
    
    class Pet
    {
        public string Name { get; set; }
        public Person Owner { get; set; }
    }
    
    public static void LeftOuterJoinExample()
    {
        Person magnus = new Person {ID = 1, FirstName = "Magnus", LastName = "Hedlund"};
        Person terry = new Person {ID = 2, FirstName = "Terry", LastName = "Adams"};
        Person charlotte = new Person {ID = 3, FirstName = "Charlotte", LastName = "Weiss"};
        Person arlene = new Person {ID = 4, FirstName = "Arlene", LastName = "Huff"};
    
        Pet barley = new Pet {Name = "Barley", Owner = terry};
        Pet boots = new Pet {Name = "Boots", Owner = terry};
        Pet whiskers = new Pet {Name = "Whiskers", Owner = charlotte};
        Pet bluemoon = new Pet {Name = "Blue Moon", Owner = terry};
        Pet daisy = new Pet {Name = "Daisy", Owner = magnus};
    
        // Create two lists.
        List<Person> people = new List<Person> {magnus, terry, charlotte, arlene};
        List<Pet> pets = new List<Pet> {barley, boots, whiskers, bluemoon, daisy};
    
        var query = from person in people
            where person.ID == 4
            join pet in pets on person equals pet.Owner  into personpets
            from petOrNull in personpets.DefaultIfEmpty()
            select new { Person=person, Pet = petOrNull}; 
    
    
    
        foreach (var v in query )
        {
            Console.WriteLine("{0,-15}{1}", v.Person.FirstName + ":", (v.Pet == null ? "Does not Exist" : v.Pet.Name));
        }
    }
    
    // This code produces the following output:
    //
    // Magnus:        Daisy
    // Terry:         Barley
    // Terry:         Boots
    // Terry:         Blue Moon
    // Charlotte:     Whiskers
    // Arlene:
    

    现在你能够 include elements from the left 即使那个元素 has no matches in the right ,在我们的例子中我们已经重新获得 Arlene ,即使他在右边没有匹配

    这是参考

    How to: Perform Left Outer Joins (C# Programming Guide)

  • 7

    如上所述:

    101 LINQ Samples - Left outer join

    var q =
        from c in categories
        join p in products on c.Category equals p.Category into ps
        from p in ps.DefaultIfEmpty()
        select new { Category = c, ProductName = p == null ? "(No products)" : p.ProductName };
    
  • 1

    扩展方法,类似于左连接和Join语法

    public static class LinQExtensions
    {
        public static IEnumerable<TResult> LeftJoin<TOuter, TInner, TKey, TResult>(
            this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, 
            Func<TOuter, TKey> outerKeySelector, 
            Func<TInner, TKey> innerKeySelector, 
            Func<TOuter, TInner, TResult> resultSelector)
        {
            return outer.GroupJoin(
                inner, 
                outerKeySelector, 
                innerKeySelector,
                (outerElement, innerElements) => resultSelector(outerElement, innerElements.FirstOrDefault()));
        }
    }
    

    刚刚在.NET核心中编写它,它似乎按预期工作 .

    小测试:

    var Ids = new List<int> { 1, 2, 3, 4};
            var items = new List<Tuple<int, string>>
            {
                new Tuple<int, string>(1,"a"),
                new Tuple<int, string>(2,"b"),
                new Tuple<int, string>(4,"d"),
                new Tuple<int, string>(5,"e"),
            };
    
            var result = Ids.LeftJoin(
                items,
                id => id,
                item => item.Item1,
                (id, item) => item ?? new Tuple<int, string>(id, "not found"));
    
            result.ToList()
            Count = 4
            [0]: {(1, a)}
            [1]: {(2, b)}
            [2]: {(3, not found)}
            [3]: {(4, d)}
    
  • 0

    我想补充一点,如果你得到MoreLinq扩展,现在支持同源和异构左连接

    http://morelinq.github.io/2.8/ref/api/html/Overload_MoreLinq_MoreEnumerable_LeftJoin.htm

    例:

    //Pretend a ClientCompany object and an Employee object both have a ClientCompanyID key on them
    
    return DataContext.ClientCompany
        .LeftJoin(DataContext.Employees,                         //Table being joined
            company => company.ClientCompanyID,                  //First key
            employee => employee.ClientCompanyID,                //Second Key
            company => new {company, employee = (Employee)null}, //Result selector when there isn't a match
            (company, employee) => new { company, employee });   //Result selector when there is a match
    

    编辑:

    回想起来,这可能有效,但它将IQueryable转换为IEnumerable,因为morelinq不会将查询转换为SQL .

    您可以使用此处所述的GroupJoin:https://stackoverflow.com/a/24273804/4251433

    这将确保它保持为IQueryable,以防您以后需要对其进行进一步的逻辑操作 .

  • 4
    class Program
    {
        List<Employee> listOfEmp = new List<Employee>();
        List<Department> listOfDepart = new List<Department>();
    
        public Program()
        {
            listOfDepart = new List<Department>(){
                new Department { Id = 1, DeptName = "DEV" },
                new Department { Id = 2, DeptName = "QA" },
                new Department { Id = 3, DeptName = "BUILD" },
                new Department { Id = 4, DeptName = "SIT" }
            };
    
    
            listOfEmp = new List<Employee>(){
                new Employee { Empid = 1, Name = "Manikandan",DepartmentId=1 },
                new Employee { Empid = 2, Name = "Manoj" ,DepartmentId=1},
                new Employee { Empid = 3, Name = "Yokesh" ,DepartmentId=0},
                new Employee { Empid = 3, Name = "Purusotham",DepartmentId=0}
            };
    
        }
        static void Main(string[] args)
        {
            Program ob = new Program();
            ob.LeftJoin();
            Console.ReadLine();
        }
    
        private void LeftJoin()
        {
            listOfEmp.GroupJoin(listOfDepart.DefaultIfEmpty(), x => x.DepartmentId, y => y.Id, (x, y) => new { EmpId = x.Empid, EmpName = x.Name, Dpt = y.FirstOrDefault() != null ? y.FirstOrDefault().DeptName : null }).ToList().ForEach
                (z =>
                {
                    Console.WriteLine("Empid:{0} EmpName:{1} Dept:{2}", z.EmpId, z.EmpName, z.Dpt);
                });
        }
    }
    
    class Employee
    {
        public int Empid { get; set; }
        public string Name { get; set; }
        public int DepartmentId { get; set; }
    }
    
    class Department
    {
        public int Id { get; set; }
        public string DeptName { get; set; }
    }
    

    OUTPUT

  • 436

    现在作为扩展方法:

    public static class LinqExt
    {
        public static IEnumerable<TResult> LeftOuterJoin<TLeft, TRight, TKey, TResult>(this IEnumerable<TLeft> left, IEnumerable<TRight> right, Func<TLeft, TKey> leftKey, Func<TRight, TKey> rightKey,
            Func<TLeft, TRight, TResult> result)
        {
            return left.GroupJoin(right, leftKey, rightKey, (l, r) => new { l, r })
                 .SelectMany(
                     o => o.r.DefaultIfEmpty(),
                     (l, r) => new { lft= l.l, rght = r })
                 .Select(o => result.Invoke(o.lft, o.rght));
        }
    }
    

    使用就像你通常使用join一样:

    var contents = list.LeftOuterJoin(list2, 
                 l => l.country, 
                 r => r.name,
                (l, r) => new { count = l.Count(), l.country, l.reason, r.people })
    

    希望这能为您节省一些时间 .

  • 0

    如果您需要加入两个以上的表,这是一个示例:

    from d in context.dc_tpatient_bookingd
    join bookingm in context.dc_tpatient_bookingm 
         on d.bookingid equals bookingm.bookingid into bookingmGroup
    from m in bookingmGroup.DefaultIfEmpty()
    join patient in dc_tpatient
         on m.prid equals patient.prid into patientGroup
    from p in patientGroup.DefaultIfEmpty()
    

    参考:https://stackoverflow.com/a/17142392/2343

  • 2

    这是一个使用方法语法的相当容易理解的版本:

    IEnumerable<JoinPair> outerLeft =
        lefts.SelectMany(l => 
            rights.Where(r => l.Key == r.Key)
                  .DefaultIfEmpty(new Item())
                  .Select(r => new JoinPair { LeftId = l.Id, RightId = r.Id }));
    
  • 34
    (from a in db.Assignments
         join b in db.Deliveryboys on a.AssignTo equals b.EmployeeId  
    
         //from d in eGroup.DefaultIfEmpty()
         join  c in  db.Deliveryboys on a.DeliverTo equals c.EmployeeId into eGroup2
         from e in eGroup2.DefaultIfEmpty()
         where (a.Collected == false)
         select new
         {
             OrderId = a.OrderId,
             DeliveryBoyID = a.AssignTo,
             AssignedBoyName = b.Name,
             Assigndate = a.Assigndate,
             Collected = a.Collected,
             CollectedDate = a.CollectedDate,
             CollectionBagNo = a.CollectionBagNo,
             DeliverTo = e == null ? "Null" : e.Name,
             DeliverDate = a.DeliverDate,
             DeliverBagNo = a.DeliverBagNo,
             Delivered = a.Delivered
    
         });
    

相关问题