Entity framework 创建表达式树以生成实体框架的参数化查询
我试图创建一个泛型类,用于为实体框架(5)组合查询 我让它工作了,唯一的问题是,值作为查询的常量而不是参数被注入。这减少了EF缓存查询并在以后重用它的可能性 这就是我目前得到的Entity framework 创建表达式树以生成实体框架的参数化查询,entity-framework,expression-trees,Entity Framework,Expression Trees,我试图创建一个泛型类,用于为实体框架(5)组合查询 我让它工作了,唯一的问题是,值作为查询的常量而不是参数被注入。这减少了EF缓存查询并在以后重用它的可能性 这就是我目前得到的 public class MinDateFilter<T> : IFilter<T> where T : class { private readonly Expression<Func<T, bool>> _predicate; public MinDa
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);
}
}
而不是
SELECT
[Extent1].[Id] AS [Id]
-- Other fields
FROM [dbo].[Candidates] AS [Extent1]
WHERE [Extent1].[CreationDate] > @p__linq__0
如果我取消注释这两个注释行并注释上面的两行,我会得到一个错误,说明参数“value”没有绑定
我希望我提供了所有有用的详细信息:)当参数作为
常量表达式传递时,如下所示:
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
你能解释一下为什么当前的结果不能满足你的需要吗?因为EF和SQL都不能使用第一个查询来正确缓存它们的输出。当然,EF将缓存已编译的查询,但除非输入完全相同,否则该缓存项将不可用。SQL Server也会发生同样的情况,它将缓存特定于此值的查询计划。我也有同样的问题。似乎无法传递Expression.Constant(myValue)。使用时,您可能会发现在检查实际工作查询时,该值作为MemberExpression传递,而不是ConstantExpression,但我仍然无法获取外部变量并使用Expression.Property或类似的方法传递它。谢谢:)我将尽快尝试:)
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Bar] AS [Bar],
FROM [dbo].[Foo] AS [Extent1]
WHERE [Extent1].[Bar] = "Some text"
Expression.Property(
Expression.Constant(new { Value = myString }),
"Value"
)
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Bar] AS [Bar],
FROM [dbo].[Foo] AS [Extent1]
WHERE [Extent1].[Bar] = @p__linq__0