Операции Join (C#)
Соединение двух источников данных — это связь объектов в одном источнике данных с объектами, которые имеют общий атрибут в другом источнике данных.
Join является важной операцией в запросах, направленных на источники данных, отношения которых друг к другу нельзя отследить напрямую. В объектно-ориентированном программировании оно может означать корреляцию между немоделируемыми объектами, например такими, как обратное направление одностороннего отношения. Примером одностороннего отношения является класс Customer, имеющий свойство типа City (город), в то время как класс City не имеет свойства, которое является коллекцией объектов Customer (клиент). В случае наличия списка объектов City для поиска всех клиентов в каждом городе можно использовать операцию соединения.
На платформе LINQ представлены методы объединения Join и GroupJoin. Они выполняют эквисоединения, или соединения, которые сопоставляют два источника данных на основе равенства их ключей. (Для сравнения, Transact-SQL поддерживает операции соединения, отличные от оператора "равно", например оператор "меньше, чем".) В терминах реляционных баз данных Join реализует внутреннее соединение — тип соединения, в котором возвращаются только те объекты, у которых есть совпадения в другом наборе данных. Метод GroupJoin не имеет прямого эквивалента в терминах реляционных баз данных, но реализует надмножество внутренних соединений и левых внешних соединений. Левое внешнее соединение — это соединение, которое возвращает каждый элемент первого (левого) источника данных, даже если в другом источнике данных не имеется соответствующих элементов.
На следующем рисунке показано концептуальное представление из двух наборов и элементов, входящих в эти наборы, которые включены либо во внутреннее соединение, либо в левое внешнее соединение.
Методы
Имя метода | Описание | Синтаксис выражения запроса C# | Дополнительные сведения |
---|---|---|---|
Join | Join две последовательности на основании функций селектора ключа и извлекает пары значений. | join … in … on … equals … |
Enumerable.Join Queryable.Join |
GroupJoin | Join две последовательности на основании функций селектора ключа и группирует полученные при сопоставлении данные для каждого элемента. | join … in … on … equals … into … |
Enumerable.GroupJoin Queryable.GroupJoin |
Примеры синтаксиса выражений запросов
Join
В следующем примере предложение join … in … on … equals …
используется для объединения двух последовательностей на основе конкретного значения.
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
В следующем примере используется предложение join … in … on … equals … into …
для объединения двух последовательностей на основе конкретного значения, а полученные совпадения для каждого элемента группируются.
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
}
См. также
- System.Linq
- Общие сведения о стандартных операторах запроса (C#)
- Анонимные типы
- Формулировка Join и запросов перекрестного произведения
- предложение join
- Join с помощью составных ключей
- Объединение содержимого из файлов разных форматов (LINQ) (C#)
- Упорядочение результатов предложения соединения
- Выполнение пользовательских операций соединения
- Выполнение групповых соединений
- Выполнение внутренних соединений
- Выполнение левых внешних соединений
- Заполнение коллекций объектов из нескольких источников (LINQ) (C#)