3

オブジェクトが「有効」である期間 (ValidFrom / ValidTo) を定義するスーパークラス「Validity」を定義しました。また、指定されたタイムスタンプに対して true を返す関数も定義します。この時点で (派生) オブジェクトが有効である場合に限ります。

public class Validity
{
    public int ValidityID { get; set; }

    public DateTime? ValidFrom { get; set; }
    public DateTime? ValidTo { get; set; }

    bool isValidAt(DateTime time)
    {
        return (ValidFrom == null || ValidFrom >= time)
            && (ValidTo == null || ValidTo < time);
    }
}

ここで、LINQ クエリ内で isValidAt をチェックする関数を書きたいと思います。これは IQueriable を介して可能だと思いますが、方法がわかりませんでした...次のコードは、何らかの方法で「機能」させたいものです (特にwhere n.isValidAt(t))。では、どうすればこれを達成できるでしょうか。

public class Node : Validity {
    public int NodeID { get; set; }

    public static getFirstNode(DateTime t)
    {
        MyContext db = new MyContext();
        var items = from n in db.Nodes
                     where n.isValidAt(t)
                     orderby n.NodeID descending
                     select n;
        return items.FirstOrDefault<Node>();
    }
}

--- ワーキングソリューション ---

Zaid Masud のソリューションを機能させるには、少し調整する必要がありました。パラメーター リストから を削除する必要があることに注意してくださいthis(現在、メソッド定義は ですpublic static IQueryable<T> isValidAt<T>(IQueryable<T> query, DateTime time) where T : Validity)。ソースコードは次のとおりです。

public class Validity
{
    public int ValidityID { get; set; }

    public DateTime? ValidFrom { get; set; }
    public DateTime? ValidTo { get; set; }

    public static IQueryable<T> isValidAt<T>(IQueryable<T> query, DateTime time) where T : Validity
    {
        return query.Where<T>(c => (c.ValidFrom == null || c.ValidFrom >= time)
            && (c.ValidTo == null || c.ValidTo < time));
    }
}
4

1 に答える 1

6

bool isValidAt(DateTime time)派生クラスがアクセスできるように、メソッドを保護されていると宣言する必要があります。

protected bool IsValidAt(DateTime time)

ただし、このコンパイルを取得した後、LINQ to SQL プロバイダーがクエリを SQL に変換できるとは思えません。おそらく、ロジックを LINQ クエリ内に埋め込み、次のように記述する必要があります。

var items = from n in db.Nodes
            where (n.ValidFrom == null || n.ValidFrom >= t) && (n.ValidTo == null || n.ValidTo < t)
            orderby n.NodeID descending
            select n;

これは機能しますが、次の種類の拡張メソッドを作成することをお勧めします。

public static class ValidityExtensions
{
    public static IQueryable<T> Valid<T>(this IQueryable<T> validities, DateTime time) where T : Validity
    {
        return validities.Where(v => (v.ValidFrom == null || ValidFrom >= time) && (v.ValidTo == null || v.ValidTo < time));
    }
}

これで、次のように使用できます。

var items = from n in db.Nodes.Valid(time)
            orderby n.NodeID descending
            select n;
于 2012-09-13T17:47:16.423 に答える