6

linq2entitiesで機能する拡張メソッドを実装しようとしています。私は当初、拡張メソッドがIQueryableを取得して返す場合、式がサポートされているメソッドのみを使用している限り、正常に機能すると想定していました。私は多くの問題を抱えていたので、最後の手段として、動作することがわかっている既存の.NET拡張メソッド(FirstOrDefault)をコピーし、名前を変更しました。メソッド自体の名前ではなく、メソッドから返された式に基づいて、「ストア式に変換できない」検証を評価するように思われます。

var prs = db.People.Where(p => p.PersonKey == 15).Select(p =>
  new
  {
    id = p.PersonKey,
    name1 = p.PersonHistories.AsQueryable().AsOf().Name
  } 
).ToList();

名前を変更したFirstOrDefaultのコピーである私の拡張メソッド:

public static TSource AsOf<TSource>(this IQueryable<TSource> source)
{
  return source.Provider.Execute<TSource>(Expression.Call(null, ((MethodInfo)MethodBase.GetCurrentMethod()).MakeGenericMethod(new Type[] { typeof(TSource) }), new Expression[] { source.Expression }));
}

エラー:

LINQ to Entities does not recognize the method 
'Models.PersonHistory AsOf[PersonHistory](System.Linq.IQueryable`1[Models.PersonHistory])' 
method, and this method cannot be translated into a store expression.

Linq2EntitiesでサポートされているIQueryable拡張メソッドを実装するにはどうすればよいですか?

AsOf(source、DateTime asOf)に本当に実行してもらいたいのは、のようなものsource.FirstOrDefault<IHistory>(s => s.EndDate > asOf && asOf >= s.StartDate )ですが、linq2entitiesでサポートされるようにこれを実現する方法がわかりません。

LINQKIT:これは私がlinqkitを使用して思いついたものであり、どういうわけかこれをより再利用可能なものに因数分解できることを望んでいます。

Expression<Func<PersonHistory, bool>> IsCurrent = (p) => p.Ends > DateTime.Now && p.Starts <= DateTime.Now;
var query = db.PersonHistories.Where(IsCurrent);
  1. ローカル変数の代わりに、よりグローバルに宣言された式を使用します。
  2. .Nowをハードコーディングする代わりに、DateTimeasOfパラメーターを追加します。
  3. そして、可能であれば、それを拡張メソッドに適合させます(この種の方法は#1と同じですが、拡張メソッドが理想的です。
4

3 に答える 3

4

これは、クエリ プロバイダーを拡張しなくても機能するはずです。それは基本的に、あなたの機能が何をしているかを正確に分解しますIsCurrent

public static class IQueryableExtensions
{
    public static IQueryable<T> IsCurrent<T>(this IQueryable<T> query,
        Expression<Func<T, DateTime?>> expressionEnd,
        Expression<Func<T, DateTime?>> expressionStart,
        DateTime asOf) where T : class
    {
        // Lambdas being sent in
        ParameterExpression paramEnd = expressionEnd.Parameters.Single();
        ParameterExpression paramStart = expressionStart.Parameters.Single();

        // GT Comparison
        BinaryExpression expressionGT = ExpressionGT(expressionEnd.Body, asOf);

        // LT Comparison
        BinaryExpression expressionLT = ExpressionLE(expressionStart.Body, asOf);

        query = query.Where(Expression.Lambda<Func<T, bool>>(expressionGT, paramEnd))
                     .Where(Expression.Lambda<Func<T, bool>>(expressionLT, paramStart));

        return query;
    }

    private static BinaryExpression ExpressionLE(Expression body, DateTime value)
    {
        return Expression.LessThanOrEqual(body, Expression.Constant(value, typeof(DateTime)));
    }

    private static BinaryExpression ExpressionGT(Expression body, DateTime value)
    {
        return Expression.GreaterThan(body, Expression.Constant(value, typeof(DateTime)));
    }
}

そして、それを使用するには

var query = db.PersonHistories.IsCurrent( p => p.Ends, 
                                          p => p.Starts, 
                                          DateTime.Now );
于 2012-06-01T14:33:31.690 に答える
3

別の質問に対する私の回答にあなたがコメントしているのを見たので、ここでも返信しようと思いました。コードにいくつかの変更と改善を加えました (コンパイルされたクエリのサポートと、式の置換に対するカスタム拡張メソッド)。

これは答えとして役立つかもしれません:

/// <summary>
/// Type helpers
/// </summary>
internal static class TypeSystem
{
    private static Type FindIEnumerable(Type seqType)
    {
        Type type;
        if (seqType == null || seqType == typeof(string) || seqType == typeof(byte[]))
        {
            return null;
        }
        else
        {
            if (!seqType.IsArray)
            {
                if (seqType.IsGenericType)
                {
                    Type[] genericArguments = seqType.GetGenericArguments();
                    int num = 0;
                    while (num < (int)genericArguments.Length)
                    {
                        Type type1 = genericArguments[num];
                        Type[] typeArray = new Type[1];
                        typeArray[0] = type1;
                        Type type2 = typeof(IEnumerable<>).MakeGenericType(typeArray);
                        if (!type2.IsAssignableFrom(seqType))
                        {
                            num++;
                        }
                        else
                        {
                            type = type2;
                            return type;
                        }
                    }
                }
                Type[] interfaces = seqType.GetInterfaces();
                if (interfaces != null && (int)interfaces.Length > 0)
                {
                    Type[] typeArray1 = interfaces;
                    int num1 = 0;
                    while (num1 < (int)typeArray1.Length)
                    {
                        Type type3 = typeArray1[num1];
                        Type type4 = TypeSystem.FindIEnumerable(type3);
                        if (type4 == null)
                        {
                            num1++;
                        }
                        else
                        {
                            type = type4;
                            return type;
                        }
                    }
                }
                if (!(seqType.BaseType != null) || !(seqType.BaseType != typeof(object)))
                {
                    return null;
                }
                else
                {
                    return TypeSystem.FindIEnumerable(seqType.BaseType);
                }
            }
            else
            {
                Type[] elementType = new Type[1];
                elementType[0] = seqType.GetElementType();
                return typeof(IEnumerable<>).MakeGenericType(elementType);
            }
        }
    }

    internal static Type GetElementType(Type seqType)
    {
        Type type = TypeSystem.FindIEnumerable(seqType);
        if (type != null)
        {
            return type.GetGenericArguments()[0];
        }
        else
        {
            return seqType;
        }
    }
}

/// <summary>
/// Marks an extension as compatible for custom linq expression expansion
/// Optionally if you can not write the extension method to fit your needs, you can provide a 
/// expression id constant for a registered expression.
/// </summary>
[AttributeUsage(AttributeTargets.Method, AllowMultiple= false, Inherited = false)]
class ExpandableQueryMethodAttribute :
    Attribute
{
    public ExpandableQueryMethodAttribute()
    {
    }
    public ExpandableQueryMethodAttribute(string expressionId)
    {
        _expressionId = expressionId;
    }

    private string _expressionId;
    public LambdaExpression TranslationExpression
    {
        get
        {
            return _expressionId != null ? QueryMethodTranslationExpressions.GetRegistered(_expressionId) : null;
        }
    }
}

/// <summary>
/// Used to register expressions for extension method to expression substitutions
/// </summary>
static class QueryMethodTranslationExpressions
{
    private static Dictionary<string, LambdaExpression> expressionList = new Dictionary<string, LambdaExpression>();

    /// <summary>
    /// Register expression
    /// </summary>
    /// <typeparam name="TFunc">type of expression delegate</typeparam>
    /// <param name="id">id constant for use with ExpandableQueryMethodAttribute</param>
    /// <param name="expr">expression</param>
    public static void RegisterExpression<TFunc>(string id, Expression<TFunc> expr)
    {
        expressionList.Add(id, expr);
    }

    public static LambdaExpression GetRegistered(string id)
    {
        //Extensions;
        return expressionList[id];
    }
}

static class Extensions
{
    /// <summary>
    /// Use on object sets before using custom extension methods, except inside compiled queries
    /// </summary>
    public static IQueryable<T> AsExtendable<T>(this IQueryable<T> source)
    {
        if (source is ExtendableQuery<T>)
        {
            return (ExtendableQuery<T>)source;
        }

        return new ExtendableQueryProvider(source.Provider).CreateQuery<T>(source.Expression);
    }
}

/// <summary>
/// Provides PlaceHolderQuery
/// 
/// No other functionality
/// </summary>
public class PlaceHolderQueryProvider : IQueryProvider
{
    public PlaceHolderQueryProvider()
    {
    }

    public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
    {
        return new PlaceHolderQuery<TElement>(this, expression);
    }

    public IQueryable CreateQuery(Expression expression)
    {
        Type elementType = TypeSystem.GetElementType(expression.Type);
        try
        {
            return (IQueryable)Activator.CreateInstance(typeof(PlaceHolderQuery<>).MakeGenericType(elementType), new object[] { this, expression });
        }
        catch (System.Reflection.TargetInvocationException tie)
        {
            throw tie.InnerException;
        }
    }

    public TResult Execute<TResult>(Expression expression)
    {
        throw new NotImplementedException();
    }

    public object Execute(Expression expression)
    {
        throw new NotImplementedException();
    }
}

/// <summary>
/// Does nothing
/// 
/// Acts only as a holder for expression
/// </summary>
public class PlaceHolderQuery<T> : IQueryable<T>, IOrderedQueryable<T>
{

    private Expression _expression;
    private PlaceHolderQueryProvider _provider;

    public PlaceHolderQuery(PlaceHolderQueryProvider provider, Expression expression)
    {
        _provider = provider;
        _expression = expression;
    }

    public IEnumerator<T> GetEnumerator()
    {
        throw new NotImplementedException();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        throw new NotImplementedException();
    }

    public Type ElementType
    {
        get
        {
            return typeof(T);
        }
    }

    public Expression Expression
    {
        get
        {
            return _expression;
        }
    }

    public IQueryProvider Provider
    {
        get
        {
            return _provider;
        }
    }
}

/// <summary>
/// Walks the expression tree and invokes custom extension methods ( to expand them ) or substitutes them with custom expressions
/// </summary>
class ExtendableVisitor : ExpressionVisitor
{
    class ExpandingVisitor : ExpressionVisitor
    {
        private Dictionary<ParameterExpression, Expression> _substitutionDictionary;

        public ExpandingVisitor(Dictionary<ParameterExpression, Expression> subDict)
        {
            _substitutionDictionary = subDict;
        }

        protected override Expression VisitParameter(ParameterExpression node)
        {
            if (_substitutionDictionary != null && _substitutionDictionary.ContainsKey(node))
                return _substitutionDictionary[node];
            else
                return base.VisitParameter(node);
        }
    }

    IQueryProvider _provider;

    internal ExtendableVisitor()
    {
        _provider = new PlaceHolderQueryProvider();
    }

    protected override Expression VisitMethodCall(MethodCallExpression node)
    {
        ExpandableQueryMethodAttribute attrib = (ExpandableQueryMethodAttribute)node.Method.GetCustomAttributes(typeof(ExpandableQueryMethodAttribute), false).FirstOrDefault();

        if (attrib != null && node.Method.IsStatic)
        {

            if (attrib.TranslationExpression != null && attrib.TranslationExpression.Parameters.Count == node.Arguments.Count)
            {
                Dictionary<ParameterExpression, Expression> subDict = new Dictionary<ParameterExpression,Expression>();

                for (int i = 0; i < attrib.TranslationExpression.Parameters.Count; i++)
                {
                    subDict.Add(attrib.TranslationExpression.Parameters[i], node.Arguments[i]);
                }

                ExpandingVisitor expander = new ExpandingVisitor(subDict);

                Expression exp = expander.Visit(attrib.TranslationExpression.Body);

                return exp;
            }
            else if (typeof(IQueryable).IsAssignableFrom(node.Method.ReturnType))
            {
                object[] args = new object[node.Arguments.Count];
                args[0] = _provider.CreateQuery(node.Arguments[0]);

                for (int i = 1; i < node.Arguments.Count; i++)
                {
                    Expression arg = node.Arguments[i];
                    args[i] = (arg.NodeType == ExpressionType.Constant) ? ((ConstantExpression)arg).Value : arg;
                }

                Expression exp = ((IQueryable)node.Method.Invoke(null, args)).Expression;

                return exp;
            }
        }            

        return base.VisitMethodCall(node);
    }
}

/// <summary>
/// Used for query compilation
/// 
/// If custom extension methods are used, the existing CompileQuery functions do not work, so I had to write this.
/// </summary>
static class CompiledExtendableQuery
{
    public static Func<TContext, TResult>
               Compile<TContext, TResult>(
       Expression<Func<TContext, TResult>> expr) where TContext : ObjectContext
    {
        return System.Data.Objects.CompiledQuery.Compile(expr.Update(new ExtendableVisitor().Visit(expr.Body), expr.Parameters));
    }

    public static Func<TContext, TArg0, TResult>
               Compile<TContext, TArg0, TResult>(
       Expression<Func<TContext, TArg0, TResult>> expr) where TContext : ObjectContext
    {
        return System.Data.Objects.CompiledQuery.Compile(expr.Update(new ExtendableVisitor().Visit(expr.Body), expr.Parameters));
    }

    public static Func<TContext, TArg0, TArg1, TResult>
               Compile<TContext, TArg0, TArg1, TResult>
      (Expression<Func<TContext, TArg0, TArg1, TResult>> expr) where TContext : ObjectContext
    {
        return System.Data.Objects.CompiledQuery.Compile(expr.Update(new ExtendableVisitor().Visit(expr.Body), expr.Parameters));
    }

    public static Func<TContext, TArg0, TArg1, TArg2, TResult>
               Compile<TContext, TArg0, TArg1, TArg2, TResult>(
       Expression<Func<TContext, TArg0, TArg1, TArg2, TResult>> expr) where TContext : ObjectContext
    {
        return System.Data.Objects.CompiledQuery.Compile(expr.Update(new ExtendableVisitor().Visit(expr.Body), expr.Parameters));
    }

    public static Func<TContext, TArg0, TArg1, TArg2, TArg3, TResult>
               Compile<TContext, TArg0, TArg1, TArg2, TArg3, TResult>(
       Expression<Func<TContext, TArg0, TArg1, TArg2, TArg3, TResult>> expr) where TContext : ObjectContext
    {
        return System.Data.Objects.CompiledQuery.Compile(expr.Update(new ExtendableVisitor().Visit(expr.Body), expr.Parameters));
    }

    public static Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TResult>
               Compile<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TResult>(
       Expression<Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TResult>> expr) where TContext : ObjectContext
    {
        return System.Data.Objects.CompiledQuery.Compile(expr.Update(new ExtendableVisitor().Visit(expr.Body), expr.Parameters));
    }

    public static Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TResult>
               Compile<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TResult>(
       Expression<Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TResult>> expr) where TContext : ObjectContext
    {
        return System.Data.Objects.CompiledQuery.Compile(expr.Update(new ExtendableVisitor().Visit(expr.Body), expr.Parameters));
    }

    public static Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TResult>
               Compile<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TResult>(
       Expression<Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TResult>> expr) where TContext : ObjectContext
    {
        return System.Data.Objects.CompiledQuery.Compile(expr.Update(new ExtendableVisitor().Visit(expr.Body), expr.Parameters));
    }

    public static Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TResult>
               Compile<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TResult>(
       Expression<Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TResult>> expr) where TContext : ObjectContext
    {
        return System.Data.Objects.CompiledQuery.Compile(expr.Update(new ExtendableVisitor().Visit(expr.Body), expr.Parameters));
    }

    public static Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TResult>
               Compile<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TResult>(
       Expression<Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TResult>> expr) where TContext : ObjectContext
    {
        return System.Data.Objects.CompiledQuery.Compile(expr.Update(new ExtendableVisitor().Visit(expr.Body), expr.Parameters));
    }

    public static Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TResult>
               Compile<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TResult>(
       Expression<Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TResult>> expr) where TContext : ObjectContext
    {
        return System.Data.Objects.CompiledQuery.Compile(expr.Update(new ExtendableVisitor().Visit(expr.Body), expr.Parameters));
    }

    public static Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TResult>
               Compile<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TResult>(
       Expression<Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TResult>> expr) where TContext : ObjectContext
    {
        return System.Data.Objects.CompiledQuery.Compile(expr.Update(new ExtendableVisitor().Visit(expr.Body), expr.Parameters));
    }

    public static Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TResult>
               Compile<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TResult>(
       Expression<Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TResult>> expr) where TContext : ObjectContext
    {
        return System.Data.Objects.CompiledQuery.Compile(expr.Update(new ExtendableVisitor().Visit(expr.Body), expr.Parameters));
    }

    public static Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TResult>
               Compile<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TResult>(
       Expression<Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TResult>> expr) where TContext : ObjectContext
    {
        return System.Data.Objects.CompiledQuery.Compile(expr.Update(new ExtendableVisitor().Visit(expr.Body), expr.Parameters));
    }

    public static Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TArg13, TResult>
               Compile<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TArg13, TResult>(
       Expression<Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TArg13, TResult>> expr) where TContext : ObjectContext
    {
        return System.Data.Objects.CompiledQuery.Compile(expr.Update(new ExtendableVisitor().Visit(expr.Body), expr.Parameters));
    }

    public static Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TArg13, TArg14, TResult>
               Compile<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TArg13, TArg14, TResult>(
       Expression<Func<TContext, TArg0, TArg1, TArg2, TArg3, TArg4, TArg5, TArg6, TArg7, TArg8, TArg9, TArg10, TArg11, TArg12, TArg13, TArg14, TResult>> expr) where TContext : ObjectContext
    {
        return System.Data.Objects.CompiledQuery.Compile(expr.Update(new ExtendableVisitor().Visit(expr.Body), expr.Parameters));
    }

}

/// <summary>
/// The query as it becomes when AsExtendable is called on it.
/// </summary>
class ExtendableQuery<T> : IQueryable<T>, IOrderedQueryable<T>
{
    ExtendableQueryProvider _provider;
    Expression _expression;

    public ExtendableQuery(ExtendableQueryProvider provider, Expression expression)
    {
        _provider = provider;
        _expression = expression;
    }

    public IEnumerator<T> GetEnumerator()
    {
        return _provider.ExecuteQuery<T>(_expression).GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public Type ElementType
    {
        get {
            return typeof(T);
        }
    }

    public Expression Expression
    {
        get {
            return _expression;    
        }
    }

    public IQueryProvider Provider
    {
        get {
            return _provider;
        }
    }


}

class ExtendableQueryProvider : IQueryProvider
{
    IQueryProvider _underlyingQueryProvider;

    private ExtendableQueryProvider()
    {
    }

    internal ExtendableQueryProvider(IQueryProvider underlyingQueryProvider)
    {
        _underlyingQueryProvider = underlyingQueryProvider;
    }

    public IQueryable<TElement> CreateQuery<TElement>(Expression expression)
    {
        return new ExtendableQuery<TElement>(this, expression);
    }

    public IQueryable CreateQuery(Expression expression)
    {
        Type elementType = TypeSystem.GetElementType(expression.Type);
        try
        {
            return (IQueryable)Activator.CreateInstance(typeof(ExtendableQuery<>).MakeGenericType(elementType), new object[] { this, expression });
        }
        catch (System.Reflection.TargetInvocationException tie)
        {
            throw tie.InnerException;
        }
    }

    internal IEnumerable<T> ExecuteQuery<T>(Expression expression)
    {
        return _underlyingQueryProvider.CreateQuery<T>(Visit(expression)).AsEnumerable();
    }

    public TResult Execute<TResult>(Expression expression)
    {
        return _underlyingQueryProvider.Execute<TResult>(Visit(expression));
    }

    public object Execute(Expression expression)
    {
        return _underlyingQueryProvider.Execute(Visit(expression));
    }

    private Expression Visit(Expression exp)
    {
        ExtendableVisitor vstr = new ExtendableVisitor();
        Expression visitedExp = vstr.Visit(exp);

        return visitedExp;
    }
}

返信が簡潔で申し訳ありません。ここは真夜中です。やらなければならない仕事があるので急がなければなりません。

ご不明な点がございましたら、お気軽にお問い合わせください。

于 2012-06-08T01:35:24.160 に答える
1

式を使用する代わりに

Expression<Func<PersonHistory, bool>> IsCurrent = (p)
    => p.Ends > DateTime.Now && p.Starts <= DateTime.Now;

var query = db.PersonHistories.Where(IsCurrent);

次のような拡張メソッドを定義できます。

public static IsCurrent Func<
    IQueryable<PersonHistory>, DateTime, IQueryable<PersonHistory>
    >()
{
    return (IQueryable<PersonHistory> query, DateTime referenceDate) =>
        query.Where(p.Ends > referenceDate && p.Starts <= referenceDate);
}

次のように使用します。

var query = IsCurrent();

var results = query(context.PeoplesHistory, referenceDate);

または:

var results = query(previousResults, referenceDate);

または、次のようにします。

public static IsCurrent Func<IQueryable<PersonHistory>, IQueryable<PersonHistory>>(
    DateTime referenceDate)
{
    return (IQueryable<PersonHistory> query) =>
        query.Where(p.Ends > referenceDate && p.Starts <= referenceDate);
}

var query = IsCurrent(refernceDate);

var results = query(context.PeoplesHistory);

そうすれば、式を構築するためのフレームワークは必要ありません。

于 2012-06-07T23:23:46.673 に答える