在我的LINQ to SQL设置中,我有各种表,这些表被映射到基本上支持相同接口(interface)以支持版本控制的类,即

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

LINQ to SQL类从此接口(interface)派生如下:
public partial class representationRevision : IValid
{
}

现在,我想定义一种过滤EntitySet<T>IEnumerable<T>IQueryable<T>的DRY(不要自己重复)方法,以便生成的列表对特定的修订版有效。我尝试这样做:
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))
            );
    }
}

但这给EntitySet<T>带来了问题。我为EntitySet添加了一个特殊的实现,该实现首先调用AsQueryable(),但这会引发异常。没想到,我尝试做一个谓词,所以我可以使用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)));
    }

当与.Where<contentRevision>(IsValidFor(revision))一起使用时,它会给出如下错误:



请注意,即使没有使用IValid接口(interface),也是如此...我一直在尝试各种有关此主题的变体(例如添加int参数),但是它们似乎总是会失败。有任何指示可以使我朝正确的方向发展吗?

最佳答案

不确定EntitySet<T>,因此将重点关注IQueryable<T>IEnumerable<T>

为了允许LINQ提供程序评估IQueryable<T>用于其表达式自变量的表达式树,需要确保保留了基础接口(interface)。否则,请按照IEnumerable<T>的方式进行所有操作(即,如果可以将整个数据集拉入本地内存,然后在本地处理而不是在数据库中进行处理,则只需使用LINQ to Objects)即可。

另一个选项是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();
}

因此,您具有使用适配器方法的共享代码。

09-17 06:20