如何在LINQ查询中指定自定义方法(C#Entity Framework)

SDw*_*rfs 3 c# linq entity-framework iqueryable

我已经定义了一个超类"有效性",它定义了一个对象是"有效"的时间跨度(ValidFrom/ValidTo).它还定义了一个函数,该函数对于给定的时间戳返回true,iff(=且当且仅当)(派生的)对象此时有效.

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我想编写一些在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>();
    }
}
Run Code Online (Sandbox Code Playgroud)

---工作解决方案---

我需要调整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));
    }
}
Run Code Online (Sandbox Code Playgroud)

Zai*_*sud 5

您需要将bool isValidAt(DateTime time)方法声明为protected,以便派生类可以访问它:

protected bool IsValidAt(DateTime time)
Run Code Online (Sandbox Code Playgroud)

但是,在您进行此编译之后,我怀疑您的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;
Run Code Online (Sandbox Code Playgroud)

这将有效,但更好的选择是创建以下类型的扩展方法:

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));
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你可以使用如下:

var items = from n in db.Nodes.Valid(time)
            orderby n.NodeID descending
            select n;
Run Code Online (Sandbox Code Playgroud)