我正在Expression<Func<Entity, bool>>動態創建運算式樹:
int id = ...;
Expression<Func<Entity, int>> keySelector = e => e.Id;
BinaryExpression equals = Expression.Equal(
keySelector.Body,
Expression.Constant(id, keySelector.Body.Type)); //replace this with a variable
var predicate = Expression.Lambda<Func<Entity, bool>>(equals, keySelector.Parameters[0]);
產生等效的e => e.Id == 1.
如何傳遞變數而不是常量:e => e.Id == id
uj5u.com熱心網友回復:
您需要將 const 更改為可以更改以下屬性的內容:
class IDHolder
{
public int Id { get; set; }
}
現在您將運算式系結到 IDHolder 的實體,如下所示:
var idHolder = new IDHolder { Id = 0 };
Expression<Func<Entity, int>> keySelector = e => e.Id;
BinaryExpression equals = Expression.Equal(
keySelector.Body,
Expression.Property(
Expression.Constant(idHolder, typeof(IDHolder)),
nameof(IDHolder.Id))
);
var predicate = Expression.Lambda<Func<Entity, bool>>(equals, keySelector.Parameters[0]);
謂詞變得稍微復雜一些,但沒有什么會使 EF 中斷:
x => x.Id == idHandler.Id
您可以通過編譯謂詞并運行更改 Id 和物體的簡單測驗來對此進行測驗:
var func = predicate.Compile();
idHolder.Id = 5;
Console.WriteLine(func(new Entity { Id = 0 }).ToString()); // false
Console.WriteLine(func(new Entity { Id = 5 }).ToString()); // true
idHolder.Id = 6;
Console.WriteLine(func(new Entity { Id = 6 }).ToString()); // true
請注意,這種方法不是執行緒安全的,如果您快取謂詞和 idHolder 并在 web api 專案或任何可能同時使用此謂詞的任何東西中使用它,則會導致奇怪的行為。要僅從請求中自動翻譯某些條件,最好在每次需要在 EF 中使用它時創建運算式。創建運算式時沒有顯著的性能影響;昂貴的操作是編譯,而 EF 從來沒有這樣做過。
或者也許我誤解了你的問題,你只需要一種方法來改變 id 的值,正如@Jochem Van Hespen 所建議的,你需要一個函式:
public Expression<Func<Entity,bool>> GetPredicate(int id){
Expression<Func<Entity, int>> keySelector = e => e.Id;
BinaryExpression equals = Expression.Equal(
keySelector.Body,
Expression.Constant(id, keySelector.Body.Type));
var predicate = Expression.Lambda<Func<Entity, bool>>(equals, keySelector.Parameters[0]);
return predicate;
}
你可以像這樣使用它:
_dbContext.Set<Entity>().Where(GetPredicate(4))
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/428910.html
下一篇:檢查強制陣列的串列元素部分
