简体   繁体   English

为EntitySet创建可重用的谓词 <T> ,IQueryable <T> 和IEnumerable <T>

[英]Making a reusable predicate for EntitySet<T>, IQueryable<T> and IEnumerable<T>

In my LINQ to SQL setup I have various tables which are mapped to classes which basically support the same interface to support versioning, ie 在我的LINQ to SQL设置中,我有各种表映射到基本上支持相同接口以支持版本控制的类,即

public interface IValid
{
    int? validTo { get; }
    int validFrom { get; }
}

The LINQ to SQL classes derive from this interface like this: LINQ to SQL类派生自此接口,如下所示:

public partial class representationRevision : IValid
{
}

Now I would like to define a DRY (Don't Repeat Yourself) way of filtering EntitySet<T> , IEnumerable<T> and IQueryable<T> so that the resulting lists are valid for a specific revision. 现在我想定义一个DRY(不要重复自己)过滤EntitySet<T>IEnumerable<T>IQueryable<T>以便生成的列表对特定修订版有效。 I've tried doing this: 我试过这样做:

public static class ExtensionMethods
{

    public static IQueryable<T> ValidFor<T>(this IQueryable<T> v, int? revision)
        where T : IValid
    {
        return v.Where(cr => ((cr.validFrom <= revision) &&
            ((cr.validTo == null) || (cr.validTo > revision)))
            || ((revision == null) && (cr.validTo == null))
            );
    }
}

But this gives problems on EntitySet<T> . 但这会给EntitySet<T>带来问题。 I added a special implementation for EntitySet which first calls AsQueryable(), but this throws an exception. 我为EntitySet添加了一个特殊的实现,它首先调用AsQueryable(),但这会引发异常。 Undeterred I tried making a predicate so I could use the Where(predicate) approach: 没有被吓倒我尝试制作一个谓词,所以我可以使用Where(predicate)方法:

    public static Expression<Func<contentRevision, bool>> IsValidFor(int? revision)
    {
        return ((cr) => ((cr.validFrom <= revision) &&
            ((cr.validTo == null) || (cr.validTo > revision)))
            || ((revision == null) && (cr.validTo == null)));
    }

When used with .Where<contentRevision>(IsValidFor(revision)) it gives errors like: .Where<contentRevision>(IsValidFor(revision)) ,会出现如下错误:

Error 5 'System.Data.Linq.EntitySet' does not contain a definition for 'Where' and the best extension method overload 错误5'System.Data.Linq.EntitySet'不包含'Where'的定义和最佳扩展方法重载
'System.Linq.Enumerable.Where (System.Collections.Generic.IEnumerable, System.Func)' has some invalid arguments 'System.Linq.Enumerable.Where(System.Collections.Generic.IEnumerable,System.Func)'有一些无效的参数

Note that this is even without using the IValid interface... I've been trying all kinds of variations on this theme (like adding the int parameter) but they all invariably seem to fail. 请注意,这甚至没有使用IValid接口...我一直在尝试这个主题的各种变化(比如添加int参数),但它们似乎总是失败。 Any pointers to get me in the right direction? 有什么指示让我朝着正确的方向前进吗?

Not sure about EntitySet<T> so will focus on IQueryable<T> and IEnumerable<T> . 不确定EntitySet<T>所以将关注IQueryable<T>IEnumerable<T>

To allow the LINQ provider to evaluate the expression trees that IQueryable<T> uses for its expression arguments one needs to ensure the underlying interface is preserved. 为了允许LINQ提供程序评估IQueryable<T>用于其表达式参数的表达式树,需要确保保留底层接口。 Otherwise do everything in term of IEnumerable<T> (ie if you are OK to pull the whole dataset into local memory and then process it there, rather than in the database, just use LINQ to Objects). 否则,根据IEnumerable<T>执行所有操作(即,如果您可以将整个数据集拉入本地内存然后在那里处理,而不是在数据库中,只需使用LINQ to Objects)。

The other option is the AsQueryable extension method (part of Queryable class) which converts a IEnumerable<T> to a IQueryable<T> , and then you can share the rest of the code. 另一个选项是AsQueryable扩展方法( Queryable类的一部分),它将IEnumerable<T>转换为IQueryable<T> ,然后您可以共享其余的代码。

IQueryable<T> SomeSharedQuery(this IQueryable<T> source) {
    return source.(LINQ query operators...);
}
IQueryable<T> SomeSharedQuery(this IEnumerable<T> source) {
    return source.AsQueryable().SomeSharedQuery();
}

So you have the shared code, with an adapter method. 所以你有共享代码,使用适配器方法。

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

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