2017-04-21 64 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