![](/img/trans.png)
[英]How to construct a dynamic where filter in EF.Core to handle equals, LIKE, gt, lt, etc
[英]How to build where predicate in EF Core in which the property selected is dynamic
我正在努力處理表達式樹和 Entity Framework Core。
我有一個方法返回我將用於過濾的表達式樹,例如:
public Expression<Func<E, bool>> GetWherePredicate<E>(Func<E, NpgsqlTsVector> selector, string queryText)
{
return entity => selector(entity).Matches(queryText);
}
然后我想用類似的東西調用這個方法:
query = query.Where(GetWherePredicate<MyEntity>(i => i.MySearchField, "the_query"));
這會產生一個錯誤,類似於:
System.InvalidOperationException: LINQ 表達式 'DbSet()
.Where(i => 調用(__selector_0, i)
.Matches(__queryText_1))' 無法翻譯。 以可翻譯的形式重寫查詢,或通過插入對“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的調用顯式切換到客戶端評估。 有關詳細信息,請參閱https://go.microsoft.com/fwlink/?linkid=2101038 。
雖然我明白為什么這不起作用,但我不確定如何解決這個問題,但懷疑它與使用表達式樹有關。 我想創建一個具有以下簽名的新 function,例如:
Expression<Func<E, bool>> GetWherePredicate<E>(MemberExpression selectorForSearchField, string queryText);
但我無法弄清楚如何采用該表達式並應用Matches
項 function。
任何幫助表示贊賞。
謝謝,埃里克
以下是回答問題的一種方法,但並不像我想的那么簡單。 或者更准確地說,我的直覺告訴我有一種更干凈、更簡單的方法。
我的(不是那么簡單)方法如下:
創建一個采用 MemberExpression 的 function(不是選擇屬性的 function),如下所示:
public Expression<Func<E, bool>> GetWherePredicate<E>(
MemberExpression member,
string queryText)
{
// Get the parameter from the member
var parameter = GetParameterExpression(member);
// Convert the query text into a constant expression
var queryTextExpression = Expression.Constant(queryText, typeof(string));
// Create an expression for the matches function
ftsMatchesFunction = typeof(NpgsqlFullTextSearchLinqExtensions).GetMethod("Matches",
BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic,
null,
new[] { typeof(NpgsqlTsVector), typeof(NpgsqlTsQuery) },
null);
var matchesExpression = Expression.Call(ftsMatchesFunction, member, partialSearchExpression);
return Expression.Lambda<Func<E, bool>>(matchesExpression, parameter);
}
然后添加謂詞,我有類似的東西:
var predicate = PredicateBuilder.New<MyEntity>(false);
var myEntity= Expression.Parameter(typeof(MyEntity), "e");
var childEntity= Expression.PropertyOrField(myEntity, nameof(Invoice.Child));
var searchProperty = Expression.PropertyOrField(childEntity, nameof(Child.FtsSearchVector));
predicate = predicate.Or(_context.GetWherePredicate<MyEntity>(
searchProperty,
"the_query_text"));
最后將過濾器添加到查詢中:
query = query.Where(predicate);
更清潔或更簡單的解決方案是不需要表達式樹的解決方案,因為需要表達式樹的唯一原因是因為我無法弄清楚如何以 ef 可以理解的方式 select 搜索屬性。
如何使用謂詞創建用於從列表中檢索對象的表達式。
方法一
使用 Predicate<generic> 類型和 IEnumerable
[Fact]
public async Task TestPredicate()
{
List<Product> products = new List<Product>
{
new Product {ProductID=1,Name="Kayak",Category="Watersports",Price=275m},
new Product {ProductID=2,Name="Lifejacket", Category="Watersports",Price=48.95m},
new Product {ProductID=3,Name="Soccer Ball", Category="Soccer",Price=19.50m},
new Product {ProductID=4,Name="Corner Flag", Category="Soccer",Price=34.95m}
};
Predicate<Product> predicate = x => x.ProductID==4;
var query=Enumerable.FirstOrDefault(products,x=>predicate(x));
if (query != null) {
output.WriteLine(query.Name);
Assert.True(true);
}
}
方法二
對謂詞使用 Expression<Func 模式:
Expression<Func<TimeAndAttendancePunchIn, bool>> predicate = e => e.EmployeeId == employeeId;
PageListViewContainer<TimeAndAttendancePunchInView> container = await taMod.TimeAndAttendance.Query().GetViewsByPage(predicate, order, pageSize, pageNumber);
public async Task<PageListViewContainer<TimeAndAttendancePunchInView>> GetViewsByPage(Expression<Func<TimeAndAttendancePunchIn, bool>> predicate, Expression<Func<TimeAndAttendancePunchIn, object>> order, int pageSize, int pageNumber)
{
var query = _unitOfWork.timeAndAttendanceRepository.GetEntitiesByExpression(predicate);
query = query.OrderByDescending(order).Select(e => e);
IPagedList<TimeAndAttendancePunchIn> list = await query.ToPagedListAsync(pageNumber, pageSize);
存儲庫
public IQueryable<TimeAndAttendancePunchIn> GetEntitiesByExpression(Expression<Func<TimeAndAttendancePunchIn, bool>> predicate)
{
var result = _dbContext.Set<TimeAndAttendancePunchIn>().Where(predicate);
return result;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.