linker buitenste join in LINQ

How to out Outer Join in C # LINQ naar objecten zonder gebruik te maken van join-on-equals-intoClauses? Is er een manier om dat te doen met whereclausule?
JUISTE PROBLEEM:
Want innerlijke join is eenvoudig en ik heb een oplossing zoals deze

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

Maar voor linker buitenste join heb ik een oplossing nodig. De mijne is zoiets, maar het werkt niet

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

Waar JoinPairis een klasse:

public class JoinPair { long leftId; long rightId; }

Antwoord 1, Autoriteit 100%

Zoals vermeld op:

101 LINQ-monsters – Links 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 };

Antwoord 2, Autoriteit 87%

Als een database-aangedreven LINQ-provider wordt gebruikt, kan een significant meer leesbare linker buitenste join als zodanig worden geschreven:

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

Als u de DefaultIfEmpty()weglaat, hebt u een innerlijke join.

Neem het geaccepteerde antwoord:

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

Deze syntaxis is erg verwarrend, en het is niet duidelijk hoe het werkt als u wilt lieten Word lid van meerdere tafels.

Opmerking
Opgemerkt moet worden dat from alias in Repo.whatever.Where(condition).DefaultIfEmpty()is hetzelfde als een buitenkant van toepassing / links-join-lateraal, welke elke (fatsoenlijke) database-optimizer is perfect in staat om in een linker join te vertalen, zolang je geen per-rij-waarden introduceert (ook bekend als een echte buitenkant). Doe dit niet in LINQ-2-objecten (omdat er geen DB-Optimizer is wanneer u LINQ-to-objecten gebruikt).

Gedetailleerd voorbeeld

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

In combinatie met LINQ 2 SQL zal het mooi vertaald worden naar de volgende zeer leesbare SQL-query:

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

Bewerken:

Zie ook ”
SQL Server-query omzetten naar Linq-query
voor een complexer voorbeeld.

Als je het doet in Linq-2-Objects (in plaats van Linq-2-SQL), moet je het op de ouderwetse manier doen (omdat LINQ naar SQL dit correct vertaalt om bewerkingen samen te voegen, maar objecten dwingt deze methode een volledige scan af en maakt geen gebruik van indexzoekopdrachten, waarom dan ook…):

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

Antwoord 3, autoriteit 23%

Lambda-expressie gebruiken

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

Antwoord 4, autoriteit 8%

Nu als uitbreidingsmethode:

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

Gebruik zoals je normaal join zou gebruiken:

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

Hopelijk bespaart dit je wat tijd.


Antwoord 5, autoriteit 7%

Bekijk dit voorbeeld.
Deze zoekopdracht zou moeten werken:

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

Antwoord 6, autoriteit 3%

Een implementatie van left outer join by extension-methoden kan er als volgt uitzien

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

De resultselector moet dan zorgen voor de null-elementen. 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));
   }

Antwoord 7, autoriteit 2%

bekijk dit voorbeeld

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:

nu kunt u include elements from the leftzelfs als dat element has no matches in the right, in ons geval hebben we Arlenezelfs hij heeft geen match aan de rechterkant

hier is de referentie

Hoe: Left Outer Joins uitvoeren (C#-programmeerhandleiding)


Antwoord 8

Dit is het algemene formulier (zoals al gegeven in andere antwoorden)

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

Hier is echter een uitleg waarvan ik hoop dat deze verduidelijkt wat dit eigenlijk betekent!

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

creëert in wezen een aparte resultatenset b_temp die in feite nul ‘rijen’ bevat voor items aan de rechterkant (items in ‘b’).

Dan de volgende regel:

from b_value in b_temp.DefaultIfEmpty()

.. herhaalt die resultaatset, waarbij de standaard null-waarde voor de ‘rij’ aan de rechterkant wordt ingesteld en het resultaat van de rij aan de rechterkant wordt ingesteld op de waarde ‘b_value’ (dwz de waarde die aan de rechterkant, als er een overeenkomend record is, of ‘null’ als dat niet het geval is).

Als de rechterkant het resultaat is van een afzonderlijke LINQ-query, bestaat deze uit anonieme typen, die alleen ‘iets’ of ‘null’ kunnen zijn. Als het echter een opsombaar is (bijvoorbeeld een lijst – waarbij MyObjectB een klasse is met 2 velden), dan is het mogelijk specifiek te zijn over welke standaard ‘null’-waarden worden gebruikt voor de eigenschappen:

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

Dit zorgt ervoor dat ‘b’ zelf niet null is (maar de eigenschappen kunnen null zijn, met behulp van de standaard null-waarden die u hebt opgegeven), en dit stelt u in staat om eigenschappen van b_value te controleren zonder een null-referentie-uitzondering te krijgen voor b_waarde. Merk op dat voor een nullable DateTime een type (DateTime?) dwz ‘nullable DateTime’ moet worden opgegeven als het ‘Type’ van de null in de specificatie voor de ‘DefaultIfEmpty’ (dit geldt ook voor typen die niet ‘natively’ zijn). ‘ nullable bijv. double, float).

Je kunt meerdere left outer joins uitvoeren door simpelweg de bovenstaande syntaxis aan elkaar te koppelen.


Antwoord 9

Hier is een voorbeeld als u aan meer dan 2 tafels moet deelnemen:

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

Ref: https://stackoverflow.com/a/17142392/2343


Antwoord 10

Extensiemethode die werkt als left join met Join-syntaxis

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

het zojuist in .NET core geschreven en het lijkt te werken zoals verwacht.

Kleine test:

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

Antwoord 11

Ik zou willen toevoegen dat als je de MoreLinq-extensie krijgt, er nu ondersteuning is voor zowel homogene als heterogene left joins

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

voorbeeld:

//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

EDIT:

Achteraf, kan dit werken, maar het converteert het Iqueryable tot een IEnumerabel als Morelinq converteert de query niet naar SQL.

U kunt in plaats daarvan een groep gebruiken zoals hier beschreven: https://stackoverflow.com/a/24273804/4251433

Hiervoor zorgt u ervoor dat het als een IQUERYABLE blijft in het geval u later verdere logische bewerkingen moet doen.


Antwoord 12

Hier is een vrij eenvoudig te begrijpen versie met behulp van methodesyntaxis:

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

Antwoord 13

Er zijn drie tafels: personen, scholen en personen_schools, die personen verbinden met de scholen die ze bestuderen. Een verwijzing naar de persoon met ID = 6 is afwezig in de tabel Personen_schools. De persoon met ID = 6 wordt echter gepresenteerd in het resultaat LEF-Gesloten raster.

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

Antwoord 14

Dit is een SQL-syntaxis die wordt vergeleken met de LINQ-syntaxis voor inner en left outer joins.
Linker buitenste join:

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

“Het volgende voorbeeld doet een groep tussen product en categorie. Dit is in wezen de linker join. De in expressie retourneert gegevens, zelfs als de categorietabel leeg is. Om toegang te krijgen tot de eigenschappen van de categorietabel, moeten we nu kiezen het traaglijke resultaat door de verklaring van CL in Catlist.defaultifeemy () toe te voegen.


Antwoord 15

Eenvoudige manier is om te gebruiken, laat trefwoord. Dit werkt voor mij.

from AItem in Db.A
Let BItem = Db.B.Where(x => x.id == AItem.id ).FirstOrDefault() 
Where SomeCondition
Select new YourViewModel
{
    X1 = AItem.a,
    X2 = AItem.b,
    X3 = BItem.c
}

Dit is een simulatie van links Join. Als elk item in B-tabel niet overeenkomen met een artikel, retourneert BITEM NULL


Antwoord 16

Voer linker buitenste joins in LINQ C # uit
// Voer linker buitenste joins uit

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/


Antwoord 17

Volgens mijn antwoord op een soortgelijke vraag, hier:

Linq naar SQL linker outer join met Lambda-syntaxis en join op 2 kolommen (samengestelde join-sleutel)

Verkrijg de code hier, of kloon mijn github-repo, en speel!

Vraag:

       var petOwners =
            from person in People
            join pet in Pets
            on new
            {
                person.Id,
                person.Age,
            }
            equals new
            {
                pet.Id,
                Age = pet.Age * 2, // owner is twice age of pet
            }
            into pets
            from pet in pets.DefaultIfEmpty()
            select new PetOwner
            {
                Person = person,
                Pet = pet,
            };

Lambda:

       var petOwners = People.GroupJoin(
            Pets,
            person => new { person.Id, person.Age },
            pet => new { pet.Id, Age = pet.Age * 2 },
            (person, pet) => new
            {
                Person = person,
                Pets = pet,
            }).SelectMany(
            pet => pet.Pets.DefaultIfEmpty(),
            (people, pet) => new
            {
                people.Person,
                Pet = pet,
            });

Antwoord 18

Als je ergens aan moet deelnemen en op moet filteren, kan dat buiten de join om. Filter kan worden gedaan na het maken van de collectie.

In dit geval, als ik dit doe in de join-voorwaarde, verklein ik de rijen die worden geretourneerd.

Ternaire voorwaarde wordt gebruikt (= n == null ? "__" : n.MonDayNote,)

  • Als het object nullis (dus geen overeenkomst), retourneer dan wat er na de ?staat. __, in dit geval.

  • Anders, geef terug wat er na de :, n.MonDayNotestaat.

Dankzij de andere bijdragers ben ik daar begonnen met mijn eigen probleem.


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

Antwoord 19

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

UITGANG


Antwoord 20

Overzicht: in dit codefragment laat ik zien hoe u op ID kunt groeperen waarbij Tabel1 en Tabel2 een één-op-veel-relatie hebben. ik groepeer op
Id, Veld1 en Veld2. De subquery is handig als een derde tabelzoekopdracht vereist is en er een left join-relatie nodig zou zijn.
Ik toon een left join grouping en een subquery linq. De resultaten zijn gelijkwaardig.

class MyView
{
public integer Id {get,set};
    public String Field1  {get;set;}
public String Field2 {get;set;}
    public String SubQueryName {get;set;}                           
}
IList<MyView> list = await (from ci in _dbContext.Table1
                                               join cii in _dbContext.Table2
                                                   on ci.Id equals cii.Id
                                               where ci.Field1 == criterion
                                               group new
                                               {
                                                   ci.Id
                                               } by new { ci.Id, cii.Field1, ci.Field2}
                                           into pg
                                               select new MyView
                                               {
                                                   Id = pg.Key.Id,
                                                   Field1 = pg.Key.Field1,
                                                   Field2 = pg.Key.Field2,
                                                   SubQueryName=
                                                   (from chv in _dbContext.Table3 where chv.Id==pg.Key.Id select chv.Field1).FirstOrDefault()
                                               }).ToListAsync<MyView>();
 Compared to using a Left Join and Group new
IList<MyView> list = await (from ci in _dbContext.Table1
                                               join cii in _dbContext.Table2
                                                   on ci.Id equals cii.Id
                       join chv in _dbContext.Table3
                                                  on cii.Id equals chv.Id into lf_chv
                                                from chv in lf_chv.DefaultIfEmpty()
                                               where ci.Field1 == criterion
                                               group new
                                               {
                                                   ci.Id
                                               } by new { ci.Id, cii.Field1, ci.Field2, chv.FieldValue}
                                           into pg
                                               select new MyView
                                               {
                                                   Id = pg.Key.Id,
                                                   Field1 = pg.Key.Field1,
                                                   Field2 = pg.Key.Field2,
                                                   SubQueryName=pg.Key.FieldValue
                                               }).ToListAsync<MyView>();

Antwoord 21

Hier is een versie van de extension-methode-oplossing met behulp van IQUERYABLE in plaats van IEnumerable

public class OuterJoinResult<TLeft, TRight>
{
    public TLeft LeftValue { get; set; }
    public TRight RightValue { get; set; }
}
public static IQueryable<TResult> LeftOuterJoin<TLeft, TRight, TKey, TResult>(this IQueryable<TLeft> left, IQueryable<TRight> right, Expression<Func<TLeft, TKey>> leftKey, Expression<Func<TRight, TKey>> rightKey, Expression<Func<OuterJoinResult<TLeft, TRight>, TResult>> result)
{
    return left.GroupJoin(right, leftKey, rightKey, (l, r) => new { l, r })
          .SelectMany(o => o.r.DefaultIfEmpty(), (l, r) => new OuterJoinResult<TLeft, TRight> { LeftValue = l.l, RightValue = r })
          .Select(result);
}

Antwoord 22

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

Antwoord 23

Eenvoudige oplossing voor de Links 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)); 

opmerkingen:

  • Om de prestaties te verbeteren kan SetB worden geconverteerd naar een Woordenboek(als dat is gebeurd, moet u dit wijzigen: !setB.Contains(stA.Id)) of een HashSet
  • Als er meer dan één veld bij betrokken is, kan dit worden bereikt met behulp van Set-bewerkingen en een klasse die het volgende implementeert: IEqualityComparer

Other episodes