2017-04-21 4 views
0

私は人々が列車のルートを検索できるmvcアプリケーションに取り組んでいます。エンティティフレームワークでデータベースをコード化しましたが、より複雑なクエリをどうやって尋ねるかわかりません。Linq - 入れ子にしたコレクションを含めるとフィルターに入れます

私は私のviewmodelで使用するルートのコレクションを持っています。最初のステップでは、どのルートに特定の開始駅と終了駅があるかを尋ねています。次に、特定の日が真に設定されているスケジュール(およびそのスケジュールの開始日と終了日が一致する場所)を含める必要があります。これは、旅行のコレクションにリンクされています(私はこのテーブルを使用してルートを1日に複数回走らせる)。ここから私は到着するすべての一致する駅を見つけることができ、テーブルのルートからの出発時間HathStations。

だから私のようなものが考えていた:

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

Filed Includeに関する質問は、StackOverflowで数多くあります。 –

+0

Stack OverFlowへようこそ。他のユーザーからの迅速な回答のために質問を正しく行う方法を知るために、サンプルの質問を参照してください。 :) Good Luck – Unbreakable

答えて

1

あなたの入力ミスは別として、あなたのプログラムにはいくつかの問題があります。

声明

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

は正しい述語を持っていません。たとえそれを述語LINQ to SQLに変更できたとしても、これをクエリとして扱う方法はわかりません。なぜなら、変数dayに応じて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のようなフラグ付き列挙型がにスケジュールあればルートは、例えば、実行が予定されているすべての日のまたは船籍の変数であるように、スケジュールのクラスを変更することを検討週末のみに実行します。

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、ルート、stはすべてルートになると予想されます。

実際に列挙しない限りあなたのシーケンス(そしてあなたのDbContextを破棄しないでください)では、Includeステートメントは必要ありません。インクルードステートメントは、特に値を要求していないが、それらをローカルメモリに入れたいときに必要です。

あなたは、テーブルの特定のフィールドを使用し、後半にあなたがそれを列挙する前に、フィールドが自動的にSQLクエリにクエリに追加し、このようにされ、このフィールドを使用していないのIQueryable、持っている場合:

var query1 = routes.Where(r.DepartureStationID == departure && r.ArrivalStationID == arrival); 
var query2 = query1.Where(route => route.Schedule.Trips...) 

余分なインクルードなしLINQ to SQLは、Scheduleテーブルとの結合が必要であることを認識しています。

私はあなたが次のルートをしたいと思います:DepartureStationに開始(1)すべてのルート

とArrivalStation に到着(2)AND日 に(3)を実行するようにスケジュールされていることと、後に予定されていますSchedule.DepartureTime (4)route.RouteHasStationsのすべてのステーションがあることを確認してください

Schedule.DepartureTimeがこのスケジュールが有効な最初の日を意味するかどうかは分かりません(ActivationDateはより良い名前?)、または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 
関連する問題