【发布时间】:2013-07-10 11:20:38
【问题描述】:
我正在尝试创建一个通用类,用于为实体框架 (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);
}
}
这个类有两种使用方式:
通过子类化它:
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
如果我取消注释两行注释并注释上面两行,我会收到一条错误消息,指出参数“值”未绑定。
我希望我提供了所有有用的细节:)
【问题讨论】:
-
你能解释一下为什么目前的结果对你来说不够好吗?
-
因为 EF 和 SQL 都不能使用第一个查询来正确缓存它们的输出。当然,EF 会缓存已编译的查询,但除非输入完全相同,否则缓存的项目将不可用。 SQL Server 也会发生同样的情况,它将缓存特定于该值的查询计划。
-
我遇到了同样的问题。看来您无法通过 Expression.Constant(myValue)。使用Expression Tree Visualizer,您可能会发现在检查实际工作查询时该值作为 MemberExpression 传递,而不是 ConstantExpression,但我仍然无法获取外部变量并使用 Expression.Property 或类似方法传递它。
标签: entity-framework expression-trees