2011-12-08 9 views
2

初めてエンティティフレームワークを使用したので、私はこのことを正しく行っているかどうかはわかりません。Linq toエンティティmany-to-many join

CustomerOrder 
------------ 
ID, StaffID, DeptID, Status, other columns... 

Staff 
------------ 
StaffID, other columns... 

StaffDept 
------------ 
StaffID, DeptID - only 2 fields 

Dept 
------------ 
DeptID, other columns... 

スタッフが複数の部門に所属することができます。

は、私は4つのテーブルを持っています。 StaffDeptテーブルは、この多対多関係を格納するためのものです。と、現在のスタッフのためではない持っ Status
  • 「進行中」のいずれかの余分なレコードを行う すべての顧客注文

    • :私はの組み合わせを取得する必要が

      Status「進捗中」

    • Statusが「進行中」のスタッフレコードは、顧客注文と同じ部門のメンバーです。例えば

    私は、次のデータがある場合:

    Staff 
    ----- 
    1, Mr X, ... 
    2, Mr Y, ... 
    
    Dept 
    ----- 
    1, Sales, ... 
    2, Marketing, ... 
    
    StaffDept 
    ----- 
    1, 1 
    1, 2 
    2, 2 
    
    CustomerOrder 
    ----- 
    1, 1, 1, In Progress, ... 
    2, 1, 1, Completed, ... 
    3, 2, 2, In Progress, ... 
    4, 2, NULL, In Progress, ... 
    

    を私は、現在のユーザが1位だった場合、彼らは顧客の注文1,2,3を見ることが期待されます。ユーザー#2は2,3,4と表示されます。ここで

    は、私がこれまで持っているコードです:作品

    from co in CustomerOrders 
    where co.Status != "In Progress" 
        || co.StaffID == @CurrentStaffID 
        || (co.StaffID != @CurrentStaffID 
         && co.DeptID!= null 
         && Staffs.Where(x => x.StaffID == @CurrentStaffID).FirstOrDefault().Depts.Any(x => x.DeptID== co.DeptID)) 
    select new CustomerOrderObject 
    { 
        Description = co.Description, 
        Amount = co.Amount, 
        ... 
    } 
    

    が、ReSharperのはFirstOrDefault()の部分は、実行時にNULL例外がスローされますと文句を言い。私はLinqpadに#3のユーザー(存在しない)を使ってテストしましたが、エラーはスローされません。私は期待していたレコード2を返します。 Resharperは上記のクエリの前に実行される別のクエリにStaffs.Where(x => x.StaffID == 3).FirstOrDefault()を取り込みたいと思っていますが、それは遅くなると思っていますか?私は本当にこのクエリのいずれかがエンティティへのlinqに新しいので、私はlinq-to-sqlを使用していたとして、データを取得する最速の方法であるかどうかはわかりません。どんなアドバイスも大歓迎です。私がしようとしているジョインのタイプを正確に記述する方法についてもわかりません。

    答えて

    2

    Staffのメンバーをプライマリキーで取得するだけで、そのIDでスタッフが1人しかいないことがわかっているので、FirstOrDefaultSingleに置き換える必要があります。

    Staffs.Single(x => x.StaffID == @CurrentStaffID).Depts.Any(x => x.DeptID== co.DeptID)) 
    

    編集1:

    おそらく、あなたは少しあなたのクエリを折ることができます。

    StaffDept.Any(sd => sd.StaffId == @CurrentStaffID && sd.DeptID== co.DeptID) 
    

    編集2:

    Staff.Any(x => x.StaffID == @CurrentStaffID && x.Depts.Any(d => d.DeptID == co.DeptID) 
    
    +0

    文句ReSharperの固定も。私が以前にしなかった理由は、Linqpadが "NotSupportedException:メソッド 'Single'と 'SingleOrDefault'を最終的なクエリ操作としてのみ使用できるというエラーをスローするということです。代わりにこのインスタンスでFirstOrDefaultメソッドを使用することを検討してください。これはエンティティにlinqでこの結合を行うための最良の方法ですか? – JumpingJezza

    +0

    @ JumpingJezza 'StaffDept'のために直進するクエリの2番目のバージョンがうまくいくかどうかを見てください。 – dasblinkenlight

    +0

    これは奇妙なことです。データベースをインポートした私のエンティティデータモデルでは、 'StaffDept'テーブルが削除され、そこで多対多の結合が行われました。私はいくつかのスマートなエンティティのフレームワークのことを仮定します – JumpingJezza