简体   繁体   中英

C# Joining two collections together

Pretty new in C# trying to Join two collections together, where the final result will provide all data from both collections. Right now the code returns only matched documents. Thank you.

//Collections
   IQueryable collection1 = database.GetCollection("MainData").AsQueryable();
   IQueryable collection2 = database.GetCollection("SecondaryData").AsQueryable(); 

          var result = collection2.Join(collection1, a => a.ID, b => b.ID, (a, b) => new { a, b })
                .ToList()
                .Select(s => new ViewModel.Customer()
                {
                    ID = s.b.ID,
                    FirstName = s.b.FirstName
                    LastName = s.b.LastName
                }).ToList();


            return result;

Ok, so you have two queries to fetch sequences of different types, let's say ClassA and ClassB . Both types have a property Id , and you want some kind of join on this Id.

... where the final result will provide all data from both collections

It's good to realize there are various types of Joins. The join you coded is the most simple join, quite often called an inner join . Only elements that have matching Ids are in the resulting sequence. So if you've got a ClassA with Id = 3, but there is no ClassB with this Id, then it won't be in your result.

IQueryable<ClassA> itemsA = ...
IQueryable<ClassB> itemsB = ...

var innerJoinResult = itemsA.Join(itemsB,   // inner join A and B
    itemA => itemA.Id,                      // from each itemA take the Id
    itemB => itemB.Id,                      // from each itemB take the Id
    (itemA, itemB) => new                   // when they match make a new object
    {                                       // where you only select the properties you want
        NameA = itemA.Name,
        NameB = itemB.Name,
        BirthdayA = itemA.Birthday,
        ...
    });

If you also want the items without matching Id, so all itemsA without a matching itemB.Id and all itemsB without a matching itemA.Id, you'll have to do a full outer join. This seems to be what you meant when you wrote:

... where the final result will provide all data from both collections

LINQ does not have this functionality as a standard, but you can write an extension method for it.

See this excellent 2nd answer in stackoverflow for a LINQ extension function for a full outer join .

Also see Extension Methods Demystified

You could use Concat which will return the items from the first collection followed by the items from the second collection:

var combined = collection1.Concat(collection2);

Or you could use Union which will return distinct values from both collections:

var combined = collection1.Union(collection2);

You can do this by also doing a reverse join from collection1 onto collection2 and then UNION on the results.

    var resultSet1 = collection2.Join(collection1, a => a.ID, b => b.ID, (a, b) => new { a, b })
          .ToList()
          .Select(s => new ViewModel.Customer()
          {
              ID = s.b.ID,
              FirstName = s.b.FirstName,
              LastName = s.b.LastName
          }).ToList();

    var resultSet2 = collection1.Join(collection2, a => a.ID, b => b.ID, (a, b) => new { a, b })
            .ToList()
            .Select(s => new ViewModel.Customer()
            {
                ID = s.b.ID,
                FirstName = s.b.FirstName,
                LastName = s.b.LastName
            }).ToList();


    return resultSet1.Union(resultSet2);

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