2013-03-28 3 views
4

Я как бы новичок в этом. Любопытно, что происходит в следующей ситуации?LINQ to SQL отложенное исполнение и материализация

var q = //MY LINQ TO SQL QUERY.Select(...) 
......... 
......... 
var c = q.Count(); 
......... 
......... 
var x = q.Where(....).Select(....); 
var y = x.ToList();//or something such that forces materialization 
var d = q.Count();//same as c 
var e = x.Count(); 
var f = y.Count(); 

Сколько раз заявления sql совершают поездку в дБ на самом деле? Однажды в Count(). Опять в Where()? Или Linq сохраняет то, что оно материализовалось во время Count()?

Или это также зависит от того, что есть где (..)? Как если бы он снова ссылался на базу данных vs, он просто ссылался на то, что было получено как часть «q»/или любых других коллекций .net и т. Д.?

Edit:

Обновленный мой код с парой других сценариев. Пожалуйста, исправьте мои ответы ниже:

q -no db trip 
c -yes, but translates to aggregate qry - select Count(*) and not a result set (as per answer below) 
x -no db trip. No matter what is written in the Where(..) 
y - yes 
d - yes - does not *reuse* c 
e - yes - select count(*) EVEN THOUGH x already materized during y 
f - no db trip 

ответ

4

При вызове Count не материализовать весь набор данных. Скорее он подготавливает и выполняет запрос, как

SELECT COUNT(*) FROM ... 

Использование ExecuteScalar, чтобы получить результат.

При вызове Where и Select это ничего не материализуются (предполагается, что q является IQueryable). Вместо этого он просто готовит запрос, например

SELECT col1, col2, ... FROM ... 

Но он фактически не выполняет его в этой точке. Он выполнит запрос только при вызове GetEnumerator по адресу q. Вы редко будете делать это непосредственно, но ничего подобного в следующем будет вызывать ваш запрос будет выполняться:

var arry = q.ToArray(); 
var list = q.ToList(); 
foreach(var rec in q) ... 

Это будет только выполнить этот запрос раз, так что наличие нескольких foreach петель не будет создавать несколько запросов к базе данных. Конечно, если вы создаете новый IQueryable на основе q (например, var q2 = q.Where(...)), он не будет привязан к результирующему набору, используемому q, поэтому ему придется снова запросить базу данных.

Я проверил ваш код в LINQPad, и, похоже, все ваши анализы верны.

Смежные вопросы