如何编写动态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表达式?

如何编写动态Lambda表达式来访问第n个父实体

应该这样做:

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; }
}