2017-04-21 63 views
0

我正在研究一个mvc应用程序,人们可以在其中搜索火车路线。我做了我的数据库代码 - 首先与实体框架,但我似乎无法弄清楚如何问一些更复杂的查询。Linq - 包含和过滤器 - 嵌套集合

我有我在viewmodel中使用的路线的集合。因此,第一步是询问哪些路线具有特定的起点和终点站。然后,我想包括某个日期设置为真的日程安排(以及该日程安排的开始日期和结束日期匹配)。这是一个旅行集合(我使用这张表导致路线一天运行多次)。从这里我可以找到所有匹配的车站,并且从航线的HADSATION到达和离开时间。

,所以我想是这样的:

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) 
} 

但这offcourse不工作。以下是我的型号:

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

请显示错误。 – DumpsterDiver

+0

有关过滤Include的问题在StackOverflow中很多。 –

+0

欢迎来到Stack OverFlow。请在SO中查看一些示例问题,以便您了解如何正确提出问题以便从其他用户获得快速答案。 :)祝你好运 – Unbreakable

回答

1

除了输入错误,您的程序还有几个问题。

声明

.Include(r => r.Schedule.where(day + "==" + true) 

没有一个正确的谓语。即使您可以将其更改为谓词,但LINQ to SQL也不知道如何将其作为查询处理,因为您需要根据变量日从调度类中调用不同的过程。

由于与包含的组合,我不确定你想要什么。从你的描述中,我会说你想要在给定的搜索日期运行的所有路线(具有特定的出发站和到达站)。

我不确定您是使用现有的数据库,还是仍在开发它。在后一种情况下,可以考虑改变计划类,以便安排是这样的

[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已标记的枚举的所有天的路线定于运行或国旗的变量,例如,如果预定仅在周末运行:

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到SQL将知道如何处理它。

如果您无法更改数据库的型号,并且您坚持使用此Schedule的定义,则无法在您的本地内存中执行它AsQueryable,但可以执行它AsEnumerable

如果您想检查您的路线是否使用函数Schedule.Monday,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),你不需要Include语句。当你没有特别要求一个值时,需要包含语句,但是你希望它们在本地存储器中。

如果你有一个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),并且被安排在 天(3)运行,为之后举行(不是吗?)Schedule.DepartureTime (4)请确保您有从route.RouteHasStations

所有站

不能确定是否Schedule.DepartureTime指的第一天,这个时间表是有效的(那样就不会ActivationDate是更好的名字?),还是DepartureTime是列车在预定日期出发的时间。

在后一种情况下,声明

.Include(sch => sch.trip.where(date > sch.DepartureTime) 

不会做你想做的:它返回的日期之后是上日期的日程安排一切,即使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