我正在使用mvc应用程序,人们可以搜索火车路线。我使用实体框架使我的数据库代码优先,但我似乎无法弄清楚如何提出一些更复杂的查询。
我有一组我在viewmodel中使用的路线。所以第一步是询问哪些路线有一个特定的起点和终点站。然后我想包括某个日期设置为true的日程表(以及该日程表的开始日期和结束日期匹配的位置)。这与一系列旅行相关联(我使用此表会导致路线在一天中多次运行)。从这里我可以找到所有匹配的站点,其中包含来自tableHasStations的到达和离开时间。
所以我想的是:
public IEnumerable<Route> Search(DateTime date, int? departure, int? arrival)
{
var day = date.DayOfWeek.ToString();
return db.Routes.Where(r => r.DepartureStationID == departure && r.ArrivalStationID == arrival)
.Include(s => s.Train)
//using linq.dynamic here
.Include(r => r.Schedule.where(day + "==" + true)
.Include(sch => sch.trip.where(date > sch.DepartureTime)
.Include(route => route.RouteHaseStations)
.Include(st => st.Stations)
}
但这是不能正常工作的。这是我的模特:
public class Route
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int RouteID { get; set; }
public String RouteName { get; set; }
[ForeignKey("Train")]
public int TrainID { get; set; }
[ForeignKey("Station")]
public int DepartureStationID { get; set; }
[ForeignKey("Station")]
public int ArrivalStationID { get; set; }
public virtual ICollection<Schedule> Schedule { get; set; }
public virtual Train Train { get; set; }
public virtual Station DepartureStation { get; set; }
public virtual Station ArrivalStation { get; set; }
}
public class Station
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int StationID { get; set; }
[Display(Name = "Station")]
public String Name { get; set; }
public int Platforms { get; set; }
public float Latitude { get; set; }
public float Longitude { get; set; }
public virtual ICollection<RouteHasStation> RouteHasStation { get; set; }
}
public class Train
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int TrainID { get; set; }
public String Name { get; set; }
public virtual ICollection<Route> Route { get; set; }
}
public class Schedule
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ScheduleID { get; set; }
[ForeignKey("Route")]
public int RouteID { get; set; }
public Boolean Monday { get; set; }
public Boolean Tuesday { get; set; }
public Boolean Wednesday { get; set; }
public Boolean Thursday { get; set; }
public Boolean Friday { get; set; }
public Boolean Saturday { get; set; }
public Boolean Sunday { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public virtual ICollection<Trip> Trip { get; set; }
public virtual Route Route { get; set; }
}
public class Trip
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int TripID { get; set; }
[ForeignKey("Schedule")]
public int ScheduleID { get; set; }
public DateTime DepartureTime { get; set; }
public virtual ICollection<RouteHasStation> RouteHasStation { get; set; }
}
public class RouteHasStation
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int RouteHasStationID { get; set; }
[ForeignKey("Station")]
public int StationID { get; set; }
public virtual Station Station { get; set; }
[ForeignKey("Trip")]
public int TripID { get; set; }
public virtual Trip Trip { get; set; }
[DataType(DataType.Time)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:HH:mm}")]
public DateTime? Arrival { get; set; }
[DataType(DataType.Time)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:HH:mm}")]
public DateTime? Departure { get; set; }
public int Platform { get; set; }
public float Distance { get; set; }
}
答案 0 :(得分:1)
除了输入错误外,您的程序还有几个问题。
声明
.Include(r => r.Schedule.where(day + "==" + true)
没有正确的谓词。即使您能够将其更改为谓词,LINQ to SQL也不知道如何将其作为查询处理,因为您需要根据变量日调用Schedule类中的其他过程。 / p>
由于与include的结合,我不确定你想要什么。根据您的描述,我想说您希望计划在指定搜索日期运行的所有路线(带有某个出发站和到站)。
我不确定您是使用现有数据库,还是仍在开发它。在后一种情况下,请考虑更改Schedule类,以便Schedule是一个标记为枚举的枚举
[Flags]
public enum MyDayOfWeek
{
Sunday = 1 << System.DayOfWeek.Sunday, // 0x01
Monday = 1 << System.DayOfWeek.Monday, // 0x02
Tuesday = 1 << System.DayOfWeek.Tuesday, // 0x04
Wednesday 1 << System.DayOfWeek.Wednesday, // 0x08
Thursday 1<< System.DayOfWeek.Thursday, // 0x10
Friday = 1 << System.DayOfWeek.Friday, // 0x20
Saturday = 1 << System.DayOfWeek.Saturday, // 0x40
}
public class Schedule
{
public int ScheduleID { get; set; }
public int RouteID { get; set; }
public MyDayOfWeek RunDays { get; set; }
public virtual ICollection<Trip> Trips {get; set;}
...
RunDays是计划运行路线的所有日期的or-flagged变量,例如,如果计划仅在周末运行:
RunDays = DayOfWeek.Saturday | DayOfWeek.Sunday;
获取计划在给定DateTime
上运行的所有路线的查询将如下:
System.DayOfWeek dayOfWeek = day.DayOfWeek;
MyDayOfWeek myDayOfWeek = (MyDayOfWeek)( 1 << (int)dayOfWeek);
var routesRunningOnDate = db
.Where(route => route.DepartureStation etc
&& (route.RunDays & myDayOfWeek) == myDayOfWeek)
Linq to SQL将知道如何处理它。
如果您无法更改数据库的型号,并且您仍然无法使用此计划的定义,则无法执行此AsQueryable
,但是可以执行它AsEnumerable
1}},在你的本地记忆中。
如果您想使用Schedule.Monday,Schedule.Tuesday等功能检查您的路线是否安排在某一天的某一天,我建议您为Schedule类定义和扩展:
public static class ScheduleExtensions
{
// returns whether schedule scheduled on date:
public static bool IsScheduled(this Schedule schedule, DateTime date)
{
switch (date.DayOfWeek)
{
case DayOfWeek.Sunday:
return schedule.Sunday;
case DayOfWeek.Monday:
return chedule.Monday;
...
}
}
}
用法:
db.Routes.AsEnumerable().Where (route => route.Schedule.IsScheduled(date));
此外,您似乎无法正确包含所有内容。你所有的参数r,s,sch,route,st都应该是路由,而实际上你的意思是你的sch是时间表等。
请注意,只要您没有真正列举您的序列(并且您不会丢弃DbContext),您就不需要包含语句。如果您没有专门询问某个值,但是您希望它们位于本地内存中,则需要包含语句。
如果您有一个IQueryable,它不使用您表的某个字段,并且您使用此字段,则在枚举之前,该字段会自动添加到查询中,从而添加到您的SQL查询中:
var query1 = routes.Where(r.DepartureStationID == departure && r.ArrivalStationID == arrival);
var query2 = query1.Where(route => route.Schedule.Trips...)
如果没有额外的包含,LINQ to SQL就知道需要使用Schedule表进行连接。
我想你想要以下路线:
(1)所有在DepartureStation上启动并到达ArrivalStation的路线 (2)计划在一天运行的AND (3)安排在(不是?)Schedule.DepartureTime之后的AND (4)确保你有来自route.RouteHasStations的所有电台
不确定Schedule.DepartureTime是否表示此计划有效的第一天(因此,激活日期不是更好的名称吗?)或者DepartureTime是否是列车在计划日期离开的时间。
在后一种情况下声明
.Include(sch => sch.trip.where(date > sch.DepartureTime)
没有做你想做的事情:即使出发时间晚于你约会的时间,它也会返回你日期之后的日期安排的所有时间表
db.Routes.Where(route => route.DepartureStaionId == departure
&& route.ArrivalStationId == arrival
&& route.Schedule.IsScheduled(date)
&& date > route.Trips.DepartureTime)
// you don't need to include Schedule and Trips explicitly
// unless you need their fields outside this query
.Include(route => route.Train)
.Include(route => route.HasTrips)
// only include these if you need their fields outside this query
// if the only thing from train you want is Train.Name,
// use route.Train.Name in a select after the Where