Сравнение удаленного и локального выполнения запросов (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>, чтобы получить возможность локального выполнения.