2017-02-06 9 views
1

私は安全追跡HRアプリを作成しています、と私は安全入射型ごとに、各月の失われた時間を返すためにLINQを使用しようとしている、ことで、グループに参加します。関連エンティティ/表の列は、次のとおりは、LINQは、合計

[safety_incident]: 
    [incident_id] 
    [incident_date] 
    [incident_type] 
    [facility_id] 

[safety_hours]: 
    [safety_hours_id] 
    [incident_id] 
    [safety_hours_date] 
    [lost_hours] 

safety_incidentとsafety_hoursの関係がsafety_hoursが特定の日付に入射するための失われた時間を記録することと、0..Nあります。私は、失われた時間が0より大きい、1年以上の事象の種類と月の組み合わせごとにレコード/オブジェクトを返そうとしています(同じカレンダー年のすべてである必要はありません)。1年間の境界や制限がない施設には、私はこれをSQLから必要なものを手に入れる:

SELECT (datepart(year,safety_hours_date) * 100 + datepart(month,safety_hours_date)), 
    inc.incident_type, sum(sh.lost_hours) 
FROM [hr].[safety_hours] sh 
INNER JOIN [hr].safety_incident inc ON sh.incident_id = inc.incident_id 
GROUP BY (datepart(year,safety_hours_date) * 100 + datepart(month,safety_hours_date)), 
    inc.incident_type 
HAVING sum(sh.lost_hours) > 0 
ORDER BY (datepart(year,safety_hours_date) * 100 + datepart(month,safety_hours_date)), 
    inc.incident_type 

私は受け入れLINQクエリに得ることができる最も近いがこれです:

var monthInjuryHours = 
       from sh in _context.safety_hours 
       where sh.safety_hours_date >= firstMonth && sh.safety_hours_date < monthAfterLast && sh.lost_hours > 0 
       join inc in _context.safety_incident on sh.incident_id equals (inc.incident_id) into most 
       from m in most 
       where (facID == 0 || m.facility_id == facID) 
       group m by new 
       { 
        m.incident_type, 
        month = new DateTime(sh.safety_hours_date.Year, sh.safety_hours_date.Month, 1) 
       } into g 
       select new 
       { 
        injury = g.Key.incident_type, 
        month = g.Key.month, 
        hours = g.Sum(h => h.lost_hours) // ERROR, can't access lost_hours 
       }; 

残念ながら、私は中lost_hoursを指定することはできません"hours"行、またはsafety_hoursの任意のプロパティは、 "h"の後に出現するsafety_incidentのものだけです。任意のヘルプ、感謝のために非常に感謝して...

編集:私はを反復処理しようとしたとき

var monthInjuryHours = 
     from inc in _context.safety_incident 
     where (facID == 0 || inc.facility_id == facID) && inc.incident_date < monthAfterLast 
     join sh in _context.safety_hours on inc.incident_id equals (sh.incident_id) into most 
     from m in most 
     where m.safety_hours_date >= firstMonth && m.safety_hours_date < monthAfterLast 
      && m.lost_hours > 0 
     group m by new 
     { 
      // Note new aliases 
      inc.incident_type, 
      month = new DateTime(m.safety_hours_date.Year, m.safety_hours_date.Month, 1) 
     } into g 
     select new 
     { 
      injury = g.Key.incident_type, 
      month = g.Key.month, 
      hours = g.Sum(h => h.lost_hours) 
     }; 

しかし:私は2つのテーブルの順序を切り替えるために、クエリを再配置することができましたし、走った何かを得ましたforeachを使用すると、 "in"キーワードを指すNotSupportedExceptionが「LINQ to Entitiesでは、パラメータのないコンストラクタと初期化子のみがサポートされています」と語りました。私はまあ、今のところ、答えは「F(orget)LINQ」である

+0

あなたは、この最小限の例を思い付くことができますか?たぶん、物事を分割することは、あなたが本当に簡単に物事を壊すことができるクエリの構文ではなく、流暢なAPIで始めるのに役立ちます。 – ridecar2

+0

問題をさらに最小限に抑える方法がわかりません。私は2つのテーブルを持っています。各テーブルには、グループ化する必要がある列があり、各グループの合計がテーブルの1つから来ています。私は純粋なLINQ構文を使用することを望んでいましたが、結局のところ賢明なハイブリッドまたは複数のステートメントが必要な場合があります。 –

答えて

0

...私は匿名型のコレクションが、何を返された他のクエリを持っていた誓います。 、私はこれが一番きれいか、最も単純な例ではありませんでした知っている

var monthInjuryHours = _context.safety_incident.Join(_context.safety_hours, 
    inc => inc.incident_id, sh => sh.incident_id, (inc, sh) => new { Inc = inc, Hours = sh }) 
    .Where(j => j.Hours.lost_hours > 0 && (facID == 0 || j.Inc.facility_id == facID) 
       && j.Inc.incident_date < monthAfterLast 
       && j.Hours.safety_hours_date >= firstMonth 
       && j.Hours.safety_hours_date < monthAfterLast).ToList() //Fixes things 
    .GroupBy(x => new { Month = new DateTime(x.Hours.safety_hours_date.Year, 
          x.Hours.safety_hours_date.Month, 1), x.Inc.incident_type }) 
    .Select(g => new { g.Key.Month, g.Key.incident_type, 
         LostHours = g.Sum(x => x.Hours.lost_hours) }) 
    .OrderBy(h => h.Month).ThenBy(h => h.incident_type); 

Yuck年代this topicに感激の答えのおかげで、ToListメソッド()はどこの後に()この構文は、私が後だった正確な結果を得るために許可しました私はそれが誰かを助けることを望む。