Join Operations (C#)
A join of two data sources is the association of objects in one data source with objects that share a common attribute in another data source.
Joining is an important operation in queries that target data sources whose relationships to each other cannot be followed directly. In object-oriented programming, this could mean a correlation between objects that is not modeled, such as the backwards direction of a one-way relationship. An example of a one-way relationship is a Customer class that has a property of type City, but the City class does not have a property that is a collection of Customer objects. If you have a list of City objects and you want to find all the customers in each city, you could use a join operation to find them.
The join methods provided in the LINQ framework are Join and GroupJoin. These methods perform equijoins, or joins that match two data sources based on equality of their keys. (For comparison, Transact-SQL supports join operators other than 'equals', for example the 'less than' operator.) In relational database terms, Join implements an inner join, a type of join in which only those objects that have a match in the other data set are returned. The GroupJoin method has no direct equivalent in relational database terms, but it implements a superset of inner joins and left outer joins. A left outer join is a join that returns each element of the first (left) data source, even if it has no correlated elements in the other data source.
The following illustration shows a conceptual view of two sets and the elements within those sets that are included in either an inner join or a left outer join.
Methods
Method Name | Description | C# Query Expression Syntax | More Information |
---|---|---|---|
Join | Joins two sequences based on key selector functions and extracts pairs of values. | join … in … on … equals … |
Enumerable.Join Queryable.Join |
GroupJoin | Joins two sequences based on key selector functions and groups the resulting matches for each element. | join … in … on … equals … into … |
Enumerable.GroupJoin Queryable.GroupJoin |
Query expression syntax examples
Join
The following example uses the join … in … on … equals …
clause to join two sequences based on specific value:
class Product
{
public string? Name { get; set; }
public int CategoryId { get; set; }
}
class Category
{
public int Id { get; set; }
public string? CategoryName { get; set; }
}
public static void Example()
{
List<Product> products = new List<Product>
{
new Product { Name = "Cola", CategoryId = 0 },
new Product { Name = "Tea", CategoryId = 0 },
new Product { Name = "Apple", CategoryId = 1 },
new Product { Name = "Kiwi", CategoryId = 1 },
new Product { Name = "Carrot", CategoryId = 2 },
};
List<Category> categories = new List<Category>
{
new Category { Id = 0, CategoryName = "Beverage" },
new Category { Id = 1, CategoryName = "Fruit" },
new Category { Id = 2, CategoryName = "Vegetable" }
};
// Join products and categories based on CategoryId
var query = from product in products
join category in categories on product.CategoryId equals category.Id
select new { product.Name, category.CategoryName };
foreach (var item in query)
{
Console.WriteLine($"{item.Name} - {item.CategoryName}");
}
// This code produces the following output:
//
// Cola - Beverage
// Tea - Beverage
// Apple - Fruit
// Kiwi - Fruit
// Carrot - Vegetable
}
GroupJoin
The following example uses the join … in … on … equals … into …
clause to join two sequences based on specific value and groups the resulting matches for each element:
class Product
{
public string? Name { get; set; }
public int CategoryId { get; set; }
}
class Category
{
public int Id { get; set; }
public string? CategoryName { get; set; }
}
public static void Example()
{
List<Product> products = new List<Product>
{
new Product { Name = "Cola", CategoryId = 0 },
new Product { Name = "Tea", CategoryId = 0 },
new Product { Name = "Apple", CategoryId = 1 },
new Product { Name = "Kiwi", CategoryId = 1 },
new Product { Name = "Carrot", CategoryId = 2 },
};
List<Category> categories = new List<Category>
{
new Category { Id = 0, CategoryName = "Beverage" },
new Category { Id = 1, CategoryName = "Fruit" },
new Category { Id = 2, CategoryName = "Vegetable" }
};
// Join categories and product based on CategoryId and grouping result
var productGroups = from category in categories
join product in products on category.Id equals product.CategoryId into productGroup
select productGroup;
foreach (IEnumerable<Product> productGroup in productGroups)
{
Console.WriteLine("Group");
foreach (Product product in productGroup)
{
Console.WriteLine($"{product.Name,8}");
}
}
// This code produces the following output:
//
// Group
// Cola
// Tea
// Group
// Apple
// Kiwi
// Group
// Carrot
}
See also
- System.Linq
- Standard Query Operators Overview (C#)
- Anonymous Types
- Formulate Joins and Cross-Product Queries
- join clause
- Join by using composite keys
- How to join content from dissimilar files (LINQ) (C#)
- Order the results of a join clause
- Perform custom join operations
- Perform grouped joins
- Perform inner joins
- Perform left outer joins
- How to populate object collections from multiple sources (LINQ) (C#)
.NET feedback
The .NET documentation is open source. Provide feedback here.
Feedback
Submit and view feedback for