Сравнение удаленного и локального выполнения запросов (LINQ to SQL)

Обновлен: November 2007

Запросы можно выполнять либо удаленно (то есть ядро базы данных выполняет запрос в базе данных) или локально (LINQ to SQL выполняет запрос в локальном кэше).

Удаленное выполнение

Рассмотрим следующий запрос:

    Dim db As New Northwnd("c:\northwnd.mdf")
    Dim c As Customer = _
(From cust In db.Customers _
Where cust.CustomerID = 19283).First()
    Dim orders = From ord In c.Orders _
        Where ord.ShippedDate.Value.Year = 1998
    For Each nextOrder In orders
        ' Do something.
    Next
            Northwnd db = new Northwnd(@"northwnd.mdf");
            Customer c = db.Customers.Single(x => x.CustomerID == "19283");
foreach (Order ord in 
    c.Orders.Where(o => o.ShippedDate.Value.Year == 1998))
{
    // Do something.
}

Если база данных содержит тысячи строк заказов, для обработки небольшого подмножества совсем не обязательно извлекать все строки. В LINQ to SQL класс EntitySet<TEntity> реализует интерфейс IQueryable. Этот метод гарантирует удаленное выполнение подобных запросов. Благодаря этому методу пользователь получает два существенных преимущества.

  • Извлекаются только необходимые данные.

  • Запросы, выполняемые ядром базы данных зачастую более эффективны благодаря индексам базы данных.

Локальное выполнение

В других случаях бывает необходимо иметь полный набор связанных записей в локальном кэше. Для этой цели класс EntitySet<TEntity> предоставляет метод Load для явной загрузки всех членов класса EntitySet<TEntity>.

Если класс EntitySet<TEntity> уже загружен, последующие запросы выполняются локально. Этот метод полезен с двух точек зрения.

  • Если полный набор необходимо использовать локально или несколько раз, можно избежать удаленных запросов и связанных с ними задержек.

  • Сущность можно сериализовать как полную сущность.

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

    Dim db As New Northwnd("c:\northwnd.mdf")
    Dim c As Customer = _
(From cust In db.Customers _
 Where cust.CustomerID = 19283).First
    c.Orders.Load()

    Dim orders = From ord In c.Orders _
        Where ord.ShippedDate.Value.Year = 1998

    For Each nextOrder In orders
        ' Do something.
    Next
            Northwnd db = new Northwnd(@"northwnd.mdf");
            Customer c = db.Customers.Single(x => x.CustomerID == "19283");
c.Orders.Load();

foreach (Order ord in 
    c.Orders.Where(o => o.ShippedDate.Value.Year == 1998))
{
    // Do something.
}

        }

Сравнение

Эти две возможности предоставляют богатое сочетание параметров: удаленное выполнение больших коллекций, локальное выполнение малых коллекций или в случаях, когда требуется вся коллекция. Удаленное выполнение реализуется с помощью интерфейса IQueryable, а локальное выполнение — посредством хранящейся в памяти коллекции IEnumerable<T>. Инструкции по принудительному локальному выполнению (то есть использованию коллекции IEnumerable<T>), см. в разделе Как преобразовать тип в общий интерфейс IEnumerable (LINQ to SQL).

Запросы к неупорядоченным наборам

Обратите внимание на важное отличие между локальной коллекцией, которая реализует метод List<T>, и коллекцией, предоставляющей удаленные запросы к неупорядоченным наборам в реляционной базе данных. Для методов List<T>, например методов, использующих значения индекса, требуется семантика списка, которая, как правило, не реализуется посредством удаленного запроса к неупорядоченному набору. По этой причине подобные методы неявно загружают класс EntitySet<TEntity>, чтобы получить возможность локального выполнения.

См. также

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

Основные понятия о запросах в LINQ to SQL