エンティティへのLINQでの週ごとのグループ化

c# entity-framework linq linq-to-entities

質問

私はユーザーが仕事に費やす時間を入力することを可能にするアプリケーションを持っています、そして私はエンティティのためにLINQを活用するために作られたいくつかの良い報告を得ようとしています。各TrackedTimeは、 DateTime 「Date」部分だけのTargetDateがあるため、ユーザーと日付で時間をグループ化するのは比較的簡単です( TrackedTimeために「where」句を省略しています)。

var userTimes = from t in context.TrackedTimes
                group t by new {t.User.UserName, t.TargetDate} into ut
                select new
                {
                    UserName = ut.Key.UserName,
                    TargetDate = ut.Key.TargetDate,
                    Minutes = ut.Sum(t => t.Minutes)
                };

DateTime.Monthプロパティのおかげで、ユーザーと月によるグループ化は少し複雑になりました。

var userTimes = from t in context.TrackedTimes
                group t by new {t.User.UserName, t.TargetDate.Month} into ut
                select new
                {
                    UserName = ut.Key.UserName,
                    MonthNumber = ut.Key.Month,
                    Minutes = ut.Sum(t => t.Minutes)
                };

今トリッキーな部分が来ます。週ごとにグループ分けする信頼できる方法はありますか? LINQ to SQLの同様の質問に対するこの回答に基づいて次のことを試みました。

DateTime firstDay = GetFirstDayOfFirstWeekOfYear();
var userTimes = from t in context.TrackedTimes
                group t by new {t.User.UserName, WeekNumber = (t.TargetDate - firstDay).Days / 7} into ut
                select new
                {
                    UserName = ut.Key.UserName,
                    WeekNumber = ut.Key.WeekNumber,
                    Minutes = ut.Sum(t => t.Minutes)
                };

しかし、LINQ to EntitiesはDateTimeオブジェクトに対する算術演算をサポートしているようには見えないので、その方法がわかりません(t.TargetDate - firstDay).Days / 7

データベースにViewを作成し、それをEntity Frameworkのコンテキストに追加してLINQクエリに追加することを検討しましたが、このような作業には多くの作業が必要です。算術的アプローチに良い回避策はありますか?データベースに触れることなくLINQステートメントに簡単に組み込めることを、エンティティへのLINQと連携する何か。ある日を別の日から引く方法を実体にLinqに伝えるいくつかの方法は?

概要

私は彼らの思慮深くそして創造的な反応についてみんなに感謝したいです。結局、この質問に対する本当の答えは「.NET 4.0まで待つ」ということです。データベース側での変更を必要とせずにEntity Frameworkを使用する応答を考え出したJacob Proffittに特に言及しながら、LINQをまだ活用している最も実用的な答えを与えるためにNoldorinに恩恵を与えるつもりです。他にも素晴らしい答えがありました。初めて質問をするのであれば、投票されたすべての質問とそのコメントを読むことを強くお勧めします。これは本当にStackOverflowの力のすばらしい例です。皆さん、ありがとうございました!

受け入れられた回答

AsEnumerable拡張メソッドの呼び出しを使用して、 AsEnumerableグループ化のためにエンティティへのLINQではなくLINQ to Objectsを使用するように強制できるはずです。

以下を試してください。

DateTime firstDay = GetFirstDayOfFirstWeekOfYear();
var userTimes = 
    from t in context.TrackedTimes.Where(myPredicateHere).AsEnumerable()
    group t by new {t.User.UserName, WeekNumber = (t.TargetDate - firstDay).Days / 7} into ut
    select new
    {
        UserName = ut.Key.UserName,
        WeekNumber = ut.Key.WeekNumber,
        Minutes = ut.Sum(t => t.Minutes)
    };

これは少なくともwhere句がLINQ to Entitiesによって実行されることを意味しますが、 group句はエンティティにとっては処理が複雑すぎるため、LINQ to Objectsによって実行されます。

運が良ければ教えてください。

更新

これは別の提案です。これにより、LINQ to Entitiesをすべての目的で使用できるようになります。

(t.TargetDate.Days - firstDay.Days) / 7

これは単にDateTime減算ではなく整数減算のみが実行されるように操作を拡張するだけです。

それは現在テストされていないので、うまくいくかもしれないし動かないかもしれません...


人気のある回答

SQLServerを使用している限り、LINQでもSQL関数を使用できます。

using System.Data.Objects.SqlClient;

var codes = (from c in _twsEntities.PromoHistory
                         where (c.UserId == userId)
                         group c by SqlFunctions.DatePart("wk", c.DateAdded) into g
                         let MaxDate = g.Max(c => SqlFunctions.DatePart("wk",c.DateAdded))
                         let Count = g.Count()
                         orderby MaxDate
                         select new { g.Key, MaxDate, Count }).ToList();

このサンプルは、このスレッドでMVP Zeeshan Hiraniから適応されました: MSDN



Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ