6

Entity Framework (5) のクエリを作成するために使用するジェネリック クラスを作成しようとしています。

私はそれを機能させました。唯一の問題は、値がパラメーターとしてではなく、クエリの定数として注入されることです。これにより、EF がクエリをキャッシュして後で再利用する可能性が低くなります。

これは私がこれまでに得たものです。

public class MinDateFilter<T> : IFilter<T> where T : class
{
    private readonly Expression<Func<T, bool>> _predicate;

    public MinDateCandidateFilter(Expression<Func<T, DateTime>> propertySelector, DateTime from)
    {
        from = from.Date.AddDays(-1);
        from = new DateTime(from.Year, from.Month, from.Day, 23, 59, 59, 999);

        Expression value = Expression.Constant(from, typeof(DateTime));
        //ParameterExpression variable = Expression.Variable(typeof(DateTime), "value");

        MemberExpression memberExpression = (MemberExpression)propertySelector.Body;
        ParameterExpression parameter = Expression.Parameter(typeof(T), "item");
        Expression exp = Expression.MakeMemberAccess(parameter, memberExpression.Member);

        Expression operation = Expression.GreaterThan(exp, value);
        //Expression operation = Expression.GreaterThan(exp, variable);
        _predicate = Expression.Lambda<Func<T, bool>>(operation, parameter);
    }

    public IQueryable<T> Filter(IQueryable<T> items)
    {
        return items.Where(_predicate);
    }
}

このクラスは、次の 2 つの方法で使用できます。

それをサブクラス化することによって:

public class MinCreationDateCandidateFilter : MinDateFilter<Candidate>
{
    public MinCreationDateCandidateFilter(DateTime @from) : base(c => c.CreationDate, @from) {}
}

または単にインスタンス化することによって:

var filter = new MinDateFilter<Entities.Transition>(t => t.Date, from.Value);

これは私がこれまでに達成したことです:

SELECT 
[Extent1].[Id] AS [Id]
-- Other fields
FROM [dbo].[Candidates] AS [Extent1]
WHERE [Extent1].[CreationDate] > convert(datetime2, '1982-12-09 23:59:59.9990000', 121)

それ以外の

SELECT 
[Extent1].[Id] AS [Id]
-- Other fields
FROM [dbo].[Candidates] AS [Extent1]
WHERE [Extent1].[CreationDate] > @p__linq__0

2 つのコメント行のコメントを外し、上記の 2 行をコメントすると、パラメーター「値」がバインドされていないというエラーが表示されます。

私はすべての有用な詳細を提供したことを願っています:)

4

1 に答える 1

13

パラメータが として渡されるとConstantExpression、次のようになります。

Expression.Constant(myString)

...結果のクエリで固定の定数シンボルが生成されます。

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[Bar] AS [Bar], 
FROM [dbo].[Foo] AS [Extent1]
WHERE [Extent1].[Bar] = "Some text"

Expression Tree Visualizer で行ったように、何らかのツールを使用して式を分析する(f => f.Bar == myString))と、パラメーターが実際にはMemberExpression. したがって、結果のクエリにパラメーターが必要な場合は、オブジェクトのプロパティのようなもの、またはより便利な匿名型を渡す必要があります。

Expression.Property(
    Expression.Constant(new { Value = myString }),
    "Value"
)

このようにして、作成したばかりのオブジェクトのプロパティを渡し、式ツリーは を取得MemberExpressionし、次のようになりますCommandText

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[Bar] AS [Bar], 
FROM [dbo].[Foo] AS [Extent1]
WHERE [Extent1].[Bar] = @p__linq__0
于 2014-02-07T19:52:50.493 に答える