Преобразует ли IQueryable в IEnumerable снова запрос?
В моем запросе мне нужно вернуть IEnumerable
, но я не знаю, приведет ли это действие к выполнению запроса снова?
var data = Repository<Person>.Find().AsEnumerable();
Find()
возвращает IQueryable
и потому, что IQueryable
наследует IEnumerable
. Я сомневаюсь, что AsEnumerable
выполняет повторное выполнение.
Я знаю, что
var data = Repository<Person>.Find().ToList()
выполняет запрос два раза. Один для Find()
и второй для Tolist()
Ответы
Ответ 1
IQueryable - это IEnumerable. Нет никакого преобразования, и поэтому никакой работы не происходит.
Работа происходит, когда вы вызываете GetEnumerator()
, либо явно, либо вызывая foreach
на нем.
Кроме того, подтвердили ли вы, что Repository.Find().ToList()
дважды вызывает SQL? Мне это не кажется правильным.
Ответ 2
AsEnumerable
фактически ничего не делает, кроме применения оператора as
к вашему IQueryable. Соответственно, любой будущий метод, который вы применяете к вашему объекту, будет использовать набор методов расширения System.Linq.Enumerable в отличие от методов System.Linq.Queryable.
Это все о отсроченном исполнении. Ничто никогда не будет выполнено против вашего запрашиваемого источника (предположительно базы данных), пока вы не попытаетесь перечислить.
Другими словами:
var data=Repository.Find().AsEnumerable()
/* The query is only actually performed AFTER here */
.ToList();
Если ваш код:
var data=Repository.Find().ToList();
выполняет запрос два раза, потому что вы делаете что-то неправильное в вашем методе Find(), что определенно не должно быть.
var data = Respository.Find();
должен выполнить запрос ZERO раз.
var result = data.ToList(); // THIS is what should execute the query.
Ответ 3
думать о linq как о "потоке", а агрегатная функция - "Flush". поток "linq to db" может только один раз промываться.
.AsEnumerable(),.Where(),.... является способом подготовки запроса
.ToList(),.First(),.Max() - это совокупность
но если вы не вызываете агрегат, тогда ваш результат linq не будет запущен. его начало работать только при его перечислении.
ех
var result = users.Select(usr => usr.Name);
ничего не произойдет здесь, пока
1 агрегат называется
result.First()
или 2 результат перечисляется
result.ToList().ForEach(...)
чтобы ответить на ваш вопрос -.Find(),.AsEnumerable() не является агрегированной функцией