Поделиться через


Перекрестные запросы между таблицами (LINQ to DataSet)

Обновлен: November 2007

Кроме запросов к отдельной таблице, LINQ to DataSet позволяет выполнять межтабличные запросы. Это делается с помощью соединения. Соединение представляет собой взаимосвязь объектов одного источника данных с объектами, использующими общий атрибут, например идентификатор продукта или контактного лица, в другом источнике данных. В объектно-ориентированном программировании связи между объектами относительно просты для перемещения, так как каждый объект содержит элементы, ссылающиеся на другой объект. Однако в таблицах внешних баз данных перемещение по связям не столь однозначно. Таблицы баз данных не содержат встроенных связей. В таких случаях для соединения элементов из разных источников может использоваться операция объединения. Например, если две таблицы содержат данные о продуктах и о продажах, нужно использовать операцию соединения для сопоставления данных о продажах и о продуктах, относящихся к одному и тому же заказу на продажу.

Платформа LINQ (Language-Integrated Query) предоставляет два оператора соединения: Join и GroupJoin. Эти операторы выполняют эквивалентные соединения, т. е. соединения, связывающие два источника данных, только если их ключи равны. (В отличие от этого, Transact-SQL поддерживает операторы соединения, отличные от equals, например оператор less than.)

В терминах реляционной базы данных оператор Join выполняет внутреннее соединение. Внутреннее соединение представляет собой соединение, при котором возвращаются только объекты, имеющие соответствия в другом наборе данных.

Операторы GroupJoin не имеют прямых аналогов в реляционных базах данных, используют надмножества внутренних соединений и левых внешних соединений. Левое внешнее соединение представляет собой соединение, возвращающее каждый элемент первой (левой) коллекции, даже если он не имеет соответствующих элементов во второй коллекции.

Дополнительные сведения о соединениях см. в разделе Операции соединения.

Пример

В следующем примере выполняется традиционное соединение таблиц SalesOrderHeader и SalesOrderDetail из образца базы данных AdventureWorks для получения заказов, сделанных через Интернет начиная с августа.

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

См. также

Основные понятия

Запросы к объектам DataSet (LINQ to DataSet)

Запросы к одиночным таблицам (LINQ to DataSet)

Запрос к типизированным объектам DataSet

Операции соединения

Другие ресурсы

Примеры LINQ to DataSet