Поскольку Linq-to-Sql использует QueryProvider
, который переводит Expression
s в операторы SQL, он должен делать это для каждого запроса, выполняемого этим провайдером (если только запрос не был предварительно скомпилирован [подробнее об этом далее)) , Так, например, на базовом уровне:
var people = context.People.Where(p => p.Name == "Matt");
Linq-to-Sql должен преобразовать выражение p => p.Name == "Matt"
в дерево выражений, которое, в свою очередь, преобразуется в оператор SQL, что-то похожее на:
SELECT t0.Name FROM People t0 WHERE t0.Name = 'Matt'
Запрос при выполнении на Sql Server, который, в свою очередь, должен сгенерировать план выполнения для запроса и запустить его для таблицы, чтобы получить результаты. Он довольно эффективен при создании правильного запроса для правильной работы и поддерживает более специализированный подход к запросам данных.
В хранимых процедурах Linq-to-Sql не нужно генерировать дерево выражений и из этого генерировать sql, вместо этого сгенерированный классом конструктор обладает всей информацией, необходимой для передачи аргументов из метода в хранимую процедуру ,
В этом смысле более эффективно использовать хранимые процедуры, но вы теряете возможность выполнять эти специальные запросы, которые так часто бывают полезны.
Вы можете обнаружить, что это действительно сводится к предпочтению использования sprocs по сравнению с прямыми запросами в вашей базе данных (обсудите это с вашим администратором баз данных).
Скомпилированные запросы предоставляют вам преимущества предварительно скомпилированного оператора (запрос генерируется только один раз), поэтому последующие запросы будут использовать ранее скомпилированный запрос. Примером может быть:
public IQueryable<Product> GetProduct(int id)
{
// Normal query, expression tree and sql generated each time it is
// it is executed against the data source.
return context.Products.Where(p => p.Id == id);
}
Принимая во внимание, что скомпилированный запрос:
private static readonly Func<DataContext, int, IQueryable<Product>> ProductById =
CompiledQuery.Compile((context, id) =>
context.Products.Where(p => p.Id == id));
public IQueryable<Product> GetProduct(int id)
{
return ProductById(context, id);
}
Последний будет использовать предварительно скомпилированный запрос, поэтому он генерирует дерево выражений и sql только один раз.