Давайте предположим, что у меня есть эти классы:Как сделать привязку EntityFramework IQueryable?
public class Car
{
public int CarId { get; set}
public virtual ICollection<Door> Doors { get; set}
}
public class Door
{
public int DoorId { get; set}
public decimal Weight { get; set}
public int CarId { get; set}
}
И я хочу сделать что-то вроде этого
foreach (var car in db.Cars)
{
var x = car.Doors.Min(d => d.Weight);
}
Как я вижу в EFTraceLog он делает что-то вроде Select * от дверей, где CarId = @. .. и вычисляет «Мин» на сервере приложений, а не на сервере db.
У меня очень большие таблицы для автомобилей и дверей, поэтому эта операция длится минуты. Но если я изменить код для этого
foreach (var car in db.Cars)
{
var x = db.Doors.Where(d => d.CarId == car.CarId).Min(d => d.Weight);
}
, то это несколько секунд.
Почему существует такая большая разница и как ее исправить? Проблема здесь состоит в том, что это гораздо более проще написать
var x = car.Doors.Min(d => d.Weight);
затем
var x = db.Doors.Where(d => d.CarId == car.CarId).Min(d => d.Weight);
Update
Мы используем Entity Framework 5.0
Update 2
Я пробовал эти варианты, они медленно
var x = car.Doors.Select(door => door.Weight).Min();
var x = car.Doors.OrderBy(x => x.Weight).Select(x => x.Weight).FirstOrDefault();
var x = car.Doors.OrderBy(x => x.Weight).Select(x => x.Weight).First();
var x = car.Doors.OrderBy(x => x.Weight).FirstOrDefault().Weight;
var x = car.Doors.OrderBy(x => x.Weight).First().Weight;
Только этот один быстрый
var x = db.Doors.Where(d => d.CarId == car.CarId).Min(d => d.Weight);
Update 3
Лучший запрос производит этот SQL
declare @p__linq__0 Int32 = cast(N'204' as Int32);
SELECT
[GroupBy1].[A1] AS [C1]
FROM (SELECT
MIN([Extent1].[Weight]) AS [A1]
FROM [dbo].[Doors] AS [Extent1]
WHERE [Extent1].[CarId] = @p__linq__0
) AS [GroupBy1]
Что SQL создает оператор 'Where' (ваша последняя строка)? – haim770
обновленный вопрос * –