简体   繁体   English

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

[英]How to specify a custom method in a LINQ query (C# Entity Framework)

I have defined a super class "Validity" which defines a time span (ValidFrom / ValidTo) in which an object is "valid". 我已经定义了一个超类“有效性”,它定义了一个对象是“有效”的时间跨度(ValidFrom / ValidTo)。 It also defines a function that returns true for a given timestamp, iff (=if and only if) a (derived) object is valid at this time. 它还定义了一个函数,该函数对于给定的时间戳返回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);
    }
}

Now I would like to write some function that checks isValidAt within a LINQ query. 现在我想编写一些在LINQ查询中检查isValidAt的函数。 I guess this is possible via IQueriable, but I didn't find out how... The following code snipped is what I want to have "working" in some way (especially the where n.isValidAt(t) ). 我想这可以通过IQueriable,但我没有找到如何...以下代码剪切是我想以某种方式“工作”(特别是在where n.isValidAt(t) )。 So, how can this be achieved? 那么,如何实现呢?

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>();
    }
}

--- WORKING SOLUTION --- ---工作解决方案---

I needed to adapt the solution of Zaid Masud a bit, to get it working. 我需要调整Zaid Masud的解决方案,以使其正常工作。 Note that I had to remove the this in the parameter list (now the method definition is public static IQueryable<T> isValidAt<T>(IQueryable<T> query, DateTime time) where T : Validity ). 请注意,我必须在参数列表中删除this (现在方法定义是public static IQueryable<T> isValidAt<T>(IQueryable<T> query, DateTime time) where T : Validity )。 Here is the source code: 这是源代码:

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));
    }
}

You need to declare your bool isValidAt(DateTime time) method as protected so the derived class can access it: 您需要将bool isValidAt(DateTime time)方法声明为protected,以便派生类可以访问它:

protected bool IsValidAt(DateTime time)

However, after you get this compiling, I doubt that your LINQ to SQL provider will be able to translate the query to SQL. 但是,在您进行此编译之后,我怀疑您的LINQ to SQL提供程序是否能够将查询转换为SQL。 You will probably need to embed the logic inside your LINQ query and write something like: 您可能需要在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;

This will work, but a better alternative is to create the following kind of extension method: 这将有效,但更好的选择是创建以下类型的扩展方法:

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));
    }
}

Now you can use this as follows: 现在你可以使用如下:

var items = from n in db.Nodes.Valid(time)
            orderby n.NodeID descending
            select n;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM