如何简化此LINQ-To-Entity查询,并使其动态化

时间:2010-12-04 08:32:58

标签: asp.net linq entity-framework-4

我有这个查询通过实体框架获取数据,该框架今天有效。事实是,我想动态地创建查询,即在块中构建它,但我无法弄清楚究竟是如何做到的。我相信如果我可以以某种方式保存我在开始时检索的一个值,我可以做到,但现在我检索它两次(可能有点慢?除非编译器在查询之前修复它)。说得通?这是LINQ:

from d in db.trains
where d.cancelled
&& d.station == toStation
&& d.date >= fromDate.Date
&& d.date <= toDate.Date
&& (from k in db.trains
    where 
    k.date == d.date
    && k.trainId == d.trainId
    && k.stationId == fromStation
    && k.position <= d.position
    select k.trainId).Contains(d.trainId)
select new
{
  trainId = d.trainId,
  date = d.date,
  arrival = d.arrival,
  departure = (from k in db.trains
               where
               k.date == d.date
               && k.trainId == d.trainId
               && k.stationId == fromStation
               && k.position <= d.position
               select k.departure).FirstOrDefault()
}
);

所以你看,为了得到离开,我必须再次找回同样的东西。所以我问的是,我可以在第一个查询中保存对象,然后以某种方式检索它吗?我无法使语法工作。

数据库看起来像这样:

trainId stationId date       arrival departure position

1       99        2010-10-11 10:00   10:10     1
1       98        2010-10-11 11:20   11:30     2
1       47        2010-10-11 12:30   12:40     3
2       99        2010-10-10 15:00   15:10     5

所以基本上,我需要从db中检索两个对象,其中第一个具有stationId x而另一个具有stationId y并且两者具有相同的日期和trainId,并且它们必须处于正确的顺序,基于在位置(火车双向,但有不同的trainId)。

此外,我希望能够动态构建此查询,如下所示:

var trains = from d in db.trains
             select d;

if (id > 0)
  trains = trains.Where(p => p.trainId == id);

if (date != DateTime.MinValue)
  trains = trains.Where(p => p.date == date);

var items = (from train in trains).ToList();

即基于各种变量是否具有值。

1 个答案:

答案 0 :(得分:1)

您可以使用let语句存储局部变量并在以后重复使用 像这样:

from d in db.trains
where d.cancelled
&& d.station == toStation
&& d.date >= fromDate.Date
&& d.date <= toDate.Date
let departures = (from k in db.trains
    where 
    k.date == d.date
    && k.trainId == d.trainId
    && k.stationId == fromStation
    && k.position <= d.position
    select k)
where departures.Select(d => d.trainId).Contains(d.trainId)
select new
{
  trainId = d.trainId,
  date = d.date,
  arrival = d.arrival,
  departure = departures.Select(d => d.departure).FirstOrDefault()
}
);