RavenDB,Linq:从嵌套层次结构

时间:2015-12-29 18:55:24

标签: linq dynamic nested ravendb

我将以下类的对象存储在ravendb数据库中:

 public class Continent
    {
       public string Id { get; set; }
       public string Name { get; set; }
       public List<Country> Countries { get; set; }
    }
    public class Country
    {
       public string Name { get; set; }
       public List<Province> Provinces { get; set; }
    }

   public class Province
   {
       public string Name { get; set; }
       public List<City> Cities { get; set; }
   }

   public class City
   {
      public string Name { get; set; }
      public string Address { get; set; }
   }

我想写一个搜索具有特定城市的大陆的方法。后者是我方法的参数。在这个方法中,我想执行如下的动态查询:query = session.Query()。Where(ConditionOnTheSearchedCity)。但我无法表达表达式&#34; ConditionOnTheSearchedCity&#34;因为我不能迭代到每个城市的名字。事实上,要创建一个基于城市名称的表达式,我尝试了以下无效的表达式:

  ParameterExpression parameterExpression = Expression.Parameter(typeof(Continent), "p");

        Expression NameExpression = Expression.PropertyOrField(
                                   Expression.PropertyOrField(
                                  Expression.PropertyOrField(
                             Expression.PropertyOrField(parameterExpression, "Countries"), "Provinces"),
                                  "Cities"),
                                   "Name");
你能帮帮我吗?提前致谢

2 个答案:

答案 0 :(得分:1)

为什么你会遇到动态构建Linq的所有麻烦? 为什么不使用RavenDB的DocumentQuery API,它允许您动态地轻松构建查询?

答案 1 :(得分:0)

正如我在评论中提到的那样,问题太广泛了,所以我只举一个例子给你一个起点。有关详细信息,请查看How to: Use Expression Trees to Build Dynamic Queries

设一个参数string cityName,想要一个像这样的过滤器

Expression<Func<Continent, bool>> filter = continent => 
    continent.Countries.Any(country =>
        country.Provinces.Any(province => 
            province.Cities.Any(city => city.Name == cityName)));

它可以像这样动态构建

var city = Expression.Parameter(typeof(City), "city");
var cityCondition = Expression.Equal(Expression.PropertyOrField(city, "Name"), Expression.Constant(cityName));
var province = Expression.Parameter(typeof(Province), "province");
var provinceCondition = Expression.Call(
    typeof(Enumerable), "Any", new[] { city.Type },
    Expression.PropertyOrField(province, "Cities"),
    Expression.Lambda(cityCondition, city));
var country = Expression.Parameter(typeof(Country), "country");
var countryCondition = Expression.Call(
    typeof(Enumerable), "Any", new[] { province.Type },
    Expression.PropertyOrField(country, "Provinces"),
    Expression.Lambda(provinceCondition, province));
var continent = Expression.Parameter(typeof(Continent), "continent");
var continentCondition = Expression.Call(
    typeof(Enumerable), "Any", new[] { country.Type },
    Expression.PropertyOrField(continent, "Countries"),
    Expression.Lambda(countryCondition, country));
var filter = Expression.Lambda<Func<Continent, bool>>(continentCondition, continent);