原谅我笨拙的解释,但我有一个包含List的类:
public class Document
{
public int OwnerId { get; set; }
public List<User> Users { get; set; }
public Document() { }
}
public class User
{
public string UserName { get; set; }
public string Department { get; set; }
}
目前我使用PredicateBuilder对我的对象执行动态查询。如何将以下LINQ语句转换为表达式树:
var predicate= PredicateBuilder.True<User>();
predicate= predicate.And<User>(user => user.Deparment == "HR");
var deptDocs = documents.AsQueryable()
.Where(doc => doc.Users
.AsQueryable().Count(predicate) > 0)
.ToList();
换句话说var deptDocs = documents.HasUserAttributes("Department", "HR").ToList();
。据我所知,如果我要发出Expression.Invoke,我的问题是无法逐行评估user => user.Deparment == "HR"
。
更新
我想我在这方面取得了一些进展:
var predicate = PredicateBuilder.True<User>();
predicate = predicate.And<User>(user => user.Department == "FIN");
Expression<Func<Document, bool>> userSelector =
doc => doc.Users
.AsQueryable()
.Any(predicate);
var docParm = Expression.Parameter(typeof(Document), "appDoc");
var body = Expression.Invoke(userSelector, docParm);
var lambda = Expression.Lambda<Func<Document, bool>>(body, docParm);
var allPredicate = PredicateBuilder.True<Document>();
allPredicate = allPredicate.And<Document>(doc => doc.OwnerId == 1);
allPredicate = allPredicate.And<Document>(lambda);
var hrDocs = this.docs.AsQueryable().Where(allPredicate).ToList();
有更有效的方法吗?如何创建一个创建谓词的表达式 - user =&gt; user.Department - 有泛型吗?
答案 0 :(得分:0)
听起来像你想要this toolkit?
答案 1 :(得分:0)
我提出了一个令人满意的解决方案,我可以使用如下语法执行查询:
var predicate = PredicateBuilder.True<Document>();
predicate = predicate.And<Document>(User.SubQuery("UserName", "DAVER"));
predicate = predicate.And<Document>(AdHoc<Document>("OwnerId", 1));
var finDocs = docs.AsQueryable().Where(predicate).ToList();
我有一个使用此方法的扩展类:
public static Expression<Func<T, bool>> AdHoc<T>
(string columnName, object compValue)
{
// Determine type of parameter
ParameterExpression parameter = Expression.Parameter(typeof(T), "x");
// Target to compare to
Expression property = Expression.Property(parameter, columnName);
// The value to match
Expression constant = Expression.Constant(compValue, compValue.GetType());
Expression equality = Expression.Equal(property, constant);
Expression<Func<T, bool>> predicate =
Expression.Lambda<Func<T, bool>>(equality, parameter);
return predicate;
}
在我的User类中,我有一个静态方法:
public static Expression<Func<Document, bool>> SubQuery(string property,
string targetValue)
{
var predicate = PredicateBuilder.True<User>();
predicate = predicate.And<User>(Extensions.AdHoc<User>(property, targetValue));
Expression<Func<Document, bool>> userSelector =
doc => doc.Users
.AsQueryable()
.Any(predicate);
var docParm = Expression.Parameter(typeof(Document), "appDoc");
var body = Expression.Invoke(userSelector, docParm);
var docPredicate = PredicateBuilder.True<Document>();
docPredicate = docPredicate.And<Document>(Expression.Lambda<Func<Document, bool>>(body, docParm));
return docPredicate;
}
缺点是我在User类本身中包含了Subquery功能。它完成了工作,但如果有人有任何建议或更好的方式来使用泛型,所以我不必在我的用户类上包含这个静态方法,我很想知道你要说的话。