Запросы между таблицами (LINQ to DataSet)Cross-Table Queries (LINQ to DataSet)

В дополнение к запросам к одной таблице можно также выполнять запросы между таблицами в LINQ to DataSet.In addition to querying a single table, you can also perform cross-table queries in LINQ to DataSet. Это делается с помощью объединения.This is done by using a join. Соединение представляет собой взаимосвязь объектов одного источника данных с объектами, использующими общий атрибут, например идентификатор продукта или контактного лица, в другом источнике данных.A join is the association of objects in one data source with objects that share a common attribute in another data source, such as a product or contact ID. В объектно-ориентированном программировании связи между объектами относительно просты для навигации, поскольку каждый объект имеет член, ссылающийся на другой объект.In object-oriented programming, relationships between objects are relatively easy to navigate because each object has a member that references another object. Однако в таблицах внешних баз данных перемещение по связям не столь однозначно.In external database tables, however, navigating relationships is not as straightforward. Таблицы баз данных не содержат встроенных связей.Database tables do not contain built-in relationships. В таких случаях для соединения элементов из разных источников может использоваться операция объединения.In these cases, the join operation can be used to match elements from each source. Например, если две таблицы содержат данные о продуктах и о продажах, нужно использовать операцию соединения для сопоставления данных о продажах и о продуктах, относящихся к одному и тому же заказу на продажу.For example, given two tables that contain product information and sales information, you could use a join operation to match sales information and products for the same sales order.

Платформа Language-Integrated query (LINQ) предоставляет два оператора Join: Join и GroupJoin .The Language-Integrated Query (LINQ) framework provides two join operators, Join and GroupJoin. Эти операторы выполняют эквивалентные объединения: то есть объединения, которые соответствуют двум источникам данных, только если их ключи равны.These operators perform equi-joins: that is, joins that match two data sources only when their keys are equal. (Напротив, Transact-SQL поддерживает операторы Join, отличные от equals , например less than оператор).(By contrast, Transact-SQL supports join operators other than equals, such as the less than operator.)

В терминах реляционной базы данных оператор Join выполняет внутреннее соединение.In relational database terms, Join implements an inner join. Внутреннее соединение представляет собой соединение, при котором возвращаются только объекты, имеющие соответствия в другом наборе данных.An inner join is a type of join in which only those objects that have a match in the opposite data set are returned.

GroupJoinОператоры не имеют прямого эквивалента в терминах реляционной базы данных; они реализуют надмножество внутренних соединений и левых внешних соединений.The GroupJoin operators have no direct equivalent in relational database terms; they implement a superset of inner joins and left outer joins. Левое внешнее соединение — это соединение, возвращающее каждый элемент первой (левой) коллекции, даже если в второй коллекции нет коррелированных элементов.A left outer join is a join that returns each element of the first (left) collection, even if it has no correlated elements in the second collection.

Дополнительные сведения о объединениях см. в разделе операции JOIN.For more information about joins, see Join Operations.

ПримерExample

В следующем примере выполняется традиционное соединение таблиц SalesOrderHeader и SalesOrderDetail из образца базы данных AdventureWorks для получения заказов, сделанных через Интернет начиная с августа.The following example performs a traditional join of the SalesOrderHeader and SalesOrderDetail tables from the AdventureWorks sample database to obtain online orders from the month of August.

// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);

DataTable orders = ds.Tables["SalesOrderHeader"];
DataTable details = ds.Tables["SalesOrderDetail"];

var query =
    from order in orders.AsEnumerable()
    join detail in details.AsEnumerable()
    on order.Field<int>("SalesOrderID") equals
        detail.Field<int>("SalesOrderID")
    where order.Field<bool>("OnlineOrderFlag") == true
    && order.Field<DateTime>("OrderDate").Month == 8
    select new
    {
        SalesOrderID =
            order.Field<int>("SalesOrderID"),
        SalesOrderDetailID =
            detail.Field<int>("SalesOrderDetailID"),
        OrderDate =
            order.Field<DateTime>("OrderDate"),
        ProductID =
            detail.Field<int>("ProductID")
    };

foreach (var order in query)
{
    Console.WriteLine("{0}\t{1}\t{2:d}\t{3}",
        order.SalesOrderID,
        order.SalesOrderDetailID,
        order.OrderDate,
        order.ProductID);
}
' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)

Dim orders As DataTable = ds.Tables("SalesOrderHeader")
Dim details As DataTable = ds.Tables("SalesOrderDetail")


Dim query = _
    From order In orders.AsEnumerable() _
    Join detail In details.AsEnumerable() _
    On order.Field(Of Integer)("SalesOrderID") Equals _
            detail.Field(Of Integer)("SalesOrderID") _
    Where order.Field(Of Boolean)("OnlineOrderFlag") = True And _
            order.Field(Of DateTime)("OrderDate").Month = 8 _
    Select New With _
    { _
        .SalesOrderID = order.Field(Of Integer)("SalesOrderID"), _
        .SalesOrderDetailID = detail.Field(Of Integer)("SalesOrderDetailID"), _
        .OrderDate = order.Field(Of DateTime)("OrderDate"), _
        .ProductID = detail.Field(Of Integer)("ProductID") _
    }

For Each order In query
    Console.WriteLine(order.SalesOrderID & vbTab & _
        order.SalesOrderDetailID & vbTab & _
        order.OrderDate & vbTab & _
        order.ProductID)
Next

См. такжеSee also