3

我已经定义了一个超类“有效性”,它定义了一个对象是“有效”的时间跨度(ValidFrom / ValidTo)。它还定义了一个函数,该函数对于给定的时间戳返回 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 回答