![](/img/trans.png)
[英]How can I convert from Expression<Func<TSource, TSourceMember>> to Func<TSource, bool> condition
[英]How to create Expression<Func<TSource, bool> by comparing Func<TSource, int> with int
我有一個帶有很多DbSet的DbContext。 每個DbSet都應該有一個函數來獲取集合中的一個頁面,具有給定的pageSize並由特定的sortOrder排序。 就像是:
var pageItems = dbContext.Posts
.Where(post => post.BlogId == blogId)
.OrderBy(some sortorder)
.Skip(pageNr * pageSize)
.Take(pageSize);
我希望能夠使用我的所有DbSet執行此操作,因此我創建了一個擴展方法,其中一個參數指定要比較的外鍵,另一個指定該外鍵應具有的值。
public static IQueryable<TSource> GetPage<TSource>(this IQueryable<TSource> source,
int pageNr, int pageSize,
Expression<Func<TSource, Tproperty>> keySelector, Tproperty comparisonValue)
{
return source
.Where( ??? )
.OrderBy(some sortorder)
.Skip(pageNr * pageSize)
.Take(pageSize);
}
如何在適合Where的謂詞中轉換keySelector?
如何在適合Where的謂詞中轉換keySelector?
這很容易,但我不知道你將如何處理訂購。 無論如何,這是你如何做你要求的:
public static IQueryable<TSource> GetPage<TSource, TKey>(this IQueryable<TSource> source,
int pageNr, int pageSize,
Expression<Func<TSource, TKey>> keySelector, TKey comparisonValue)
{
var predicate = Expression.Lambda<Func<TSource, bool>>(
Expression.Equal(keySelector.Body, Expression.Constant(comparisonValue)),
keySelector.Parameters);
return source
.Where(predicate)
//.OrderBy(some sortorder) ??
.Skip(pageNr * pageSize)
.Take(pageSize);
}
您正在尋找一種從Expression<Func<TSource, Tproperty>> keySelector
和Tproperty comparisonValue
獲取Expression<Func<TSource, boolean>>
的方法,以便它可以通過以下方式轉換為商店表達式:實體框架。
這意味着瑣碎
public static Expression<Func<TSource, bool>> KeyPredicateNaive<TSource, Tproperty>(Expression<Func<TSource, Tproperty>> keySelector, Tproperty comparisonValue)
{
return (TSource source) =>EqualityComparer<Tproperty>.Default.Equals(keySelector.Compile()(source), comparisonValue);
}
不行。 這不能轉換為商店表達式。
我們需要手動構造表達式。 我們需要的是一個使用鍵選擇器作為其左值的相等表達式,以及一個將比較值作為值作為其右值的常量表達式。 我們可以構建如下:
public static Expression<Func<TSource, bool>> KeyPredicate<TSource, Tproperty>(Expression<Func<TSource, Tproperty>> keySelector, Tproperty comparisonValue)
{
var bd = Expression.Equal(keySelector.Body, Expression.Constant(comparisonValue));
return Expression.Lambda<Func<TSource, bool>>(bd, keySelector.Parameters);
}
結果可以傳遞給你的where類。 減肥(這樣它將編譯和運行),你的方法將是
public static IQueryable<TSource> GetPage<TSource>(this IQueryable<TSource> source,
int pageSize,
Expression<Func<TSource, Tproperty>> keySelector, Tproperty comparisonValue)
{
return source
.Where(KeyPredicate(keySelector, comparisonValue)
.Take(pageSize);
}
我會用這個嗎? 可能不是。 全方位將謂詞作為lambda直接傳遞給函數,而不是自己構造表達式。 但這肯定是一種可能性。
您正在為可查詢源編寫擴展,是嗎? 所以只需傳遞表達式和過濾源:
public static IQueryable<TSource> GetPage<TSource, TKey>(this IQueryable<TSource> source,
Expression<Func<TSource, bool>> predicate,
Expression<Func<TSource, TKey>> keySelector,
int pageNr, int pageSize
)
{
return source
.Where(predicate)
.OrderBy(keySelector)
.Skip(pageNr * pageSize)
.Take(pageSize);
}
用法:
db.Posts.GetPage(p => p.Author == "Bob", p => p.Date, 5, 10);
注意 :在你的方法中你有排序問題(第二個表達式),所有你得到的是傳遞兩個參數p => p.Author, "Bob"
而不是傳遞一個現成的表達式p => p.Author == "Bob"
。
但我會將謂詞和keySelector移出GetPage
方法。 讓這個方法只關注分頁 (作為方法名稱狀態):
public static IQueryable<TSource> GetPage<TSource, TKey>(this IQueryable<TSource> source,
int pageNr, int pageSize)
{
return source.Skip(pageNr * pageSize).Take(pageSize);
}
用法:
db.Posts.Where(p => p.Author == "Bob").OrderBy(p => p.Date).GetPage(5, 10);
或者如果你有存儲庫
postsRepository.GetByAuthor("Bob").GetPage(5, 10);
嘗試這個,看看它是否有幫助
Expression<Func<TSource, bool>> keySelector
或者干脆
Func<TSource, bool> keySelector
鑒於此代碼:
sealed class SwapVisitor : ExpressionVisitor
{
private readonly Expression _from;
private readonly Expression _to;
public SwapVisitor(Expression from, Expression to)
{
_from = from;
_to = to;
}
public override Expression Visit(Expression node)
{
return node == _from ? _to : base.Visit(node);
}
}
static Expression<Func<TInput, bool>> Combine<TInput, TOutput>(
Expression<Func<TInput, TOutput>> transform,
Expression<Func<TOutput, bool>> predicate)
{
var swap = new SwapVisitor(predicate.Parameters[0], transform.Body);
return Expression.Lambda<Func<TInput, bool>>(
swap.Visit(predicate.Body), transform.Parameters);
}
您可以:
.Where(Combine(keySelector, key => key == comparisonValue))
這就是創建一個新的Expression
,其中包含傳遞的表達式keySelector
的主體和用於比較的新表達式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.