如何编写动态Lambda表达式来访问第n个父实体
本文关键字:实体 访问 何编写 动态 Lambda 表达式 | 更新日期: 2023-09-27 18:16:49
我有一个应用程序使用nhibernate和linq对数据库进行查询。一切都很好,但我有以下模型映射(与自动相关):
public class A
{
public virtual int Id { get; set; }
public virtual A ParentA { get; set; }
}
我有一个处理一些信息的方法,这个方法取一个count
整数参数。我想知道是否有任何方法可以访问count
乘以ParentA属性来创建过滤器。
protected void Proccess(int count, int id)
{
var query = session.Query<A>();
// I would like to access, the number of count variable in parentA property, something like:
// for sample: if count is 3, I would like a query like:
query.Where(x => x.ParentA.ParentA.ParentA.Id == id);
// maybe something like this:
for (int i = 0; i < count; i++)
{
query.Where(x => x.ParentA.ParentA.ParentA.Id == id);
}
var result = query.ToList();
// continue method...
}
是否有任何方法来创建这种Lambda表达式?
应该这样做:
protected void Process(int count, int id)
{
var query = session.Query<A>().Where(BuildFilter(count,id));
var result = query.ToList();
}
private static Expression<Func<A, bool>> BuildFilter(int count, int id)
{
var x = Expression.Parameter(typeof(A), "x");
Expression instance = x;
if (count != 0)
{
var prop = typeof(A).GetProperty("ParentA");
while (count > 0)
{
instance = Expression.Property(instance, prop);
count--;
}
}
var instanceId = Expression.Property(instance, "Id");
var compareId = Expression.Constant(id);
var body = Expression.Equal(instanceId, compareId);
return Expression.Lambda<Func<A, bool>>(body, x);
}
生成的SQL将不会像Richard Deeming的答案那样"漂亮",但是它的优点是对于那些不知道System.Linq.Expression
名称空间的人来说是可读的。
protected List<A> Proccess(int count, int id)
{
var query = session.Query<A>()
.Select(x => new Pair { Item = x, Ancestor = x };
Func<IQueryable<Pair>, IQueryable<Pair>> addNesting
= q.Select(x => new Pair{ Item = x.Item, Ancestor = Ancestor.Parent });
foreach(var i in Enumerable.Range(0, count))
{
query = addNesting(query);
}
return query.Where(x => x.Ancestor == id).Select(x => x.Item).ToList();
}
private class Pair
{
public A Item {get;set;}
public A Ancestor { get; set; }
}