我試圖創建一個泛型類來用於組成實體框架(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
如果我取消這兩個註釋行,我的評論上面的兩個,我得到一個錯誤,指出參數「值」未綁定。
我希望我給所有有用的細節:)
你能解釋一下爲什麼不是當前結果你不夠好? – svick
因爲EF和SQL都不能使用第一個查詢來正確緩存其輸出。 當然,EF會緩存已編譯的查詢,但除非輸入完全相同,否則該緩存項目將不可用。 對於將緩存特定於此值的查詢計劃的SQL Server也會發生同樣的情況。 – Kralizek
我遇到同樣的問題。看來你不能傳遞Expression.Constant(myValue)。使用[Expression Tree Visualizer](http://exprtreevisualizer.codeplex.com/)時,您可能會發現在檢查實際工作查詢時,該值是作爲MemberExpression傳遞的,而不是ConstantExpression,但我仍無法獲取外部變量並通過Expression.Property或類似的方式傳遞它。 –