创建动态查询


想在项目中实现一个灵活的动态查询类,参考http://www.cnblogs.com/lyj/archive/2008/03/25/1122157.html和http://www.cnblogs.com/killuakun/archive/2008/08/03/1259389.html后写了一段Demo,发现代码在VS2012 EF4.5中会抛如下异常:



相同的代码在VS2008 EF3.5中是可以正常运行的:




纠结万分后找到解决方法,代码如下:


  1. OscarEntities db = new OscarEntities(); 
  2. IQueryable<City> cities = db.Citys; 
  3. ParameterExpression param = Expression.Parameter(typeof(City), "c"); 
  4. Expression left = Expression.Property(param, typeof(City).GetProperty("Name")); 
  5. Expression right = Expression.Constant("北京市"); 
  6. Expression filter = Expression.Equal(left, right); 
  7. //Expression pred = Expression.Lambda(filter, param); 
  8. //Expression expr = Expression.Call(typeof(Queryable), "Where", new Type[] { typeof(City) }, 
  9. //    Expression.Constant(cities), pred); 
  10. //var result = db.Citys.AsQueryable().Provider.CreateQuery<City>(expr); 
  11. var result = db.Citys.Where(Expression.Lambda<Func<City, bool>>(filter, param)); 
  12. list.DataSource = result.ToList(); 
  13. list.DisplayMember = "Name"
            OscarEntities db = new OscarEntities();
            IQueryable<City> cities = db.Citys;
            ParameterExpression param = Expression.Parameter(typeof(City), "c");
            Expression left = Expression.Property(param, typeof(City).GetProperty("Name"));
            Expression right = Expression.Constant("北京市");
            Expression filter = Expression.Equal(left, right);
            //Expression pred = Expression.Lambda(filter, param);
            //Expression expr = Expression.Call(typeof(Queryable), "Where", new Type[] { typeof(City) },
            //    Expression.Constant(cities), pred);
            //var result = db.Citys.AsQueryable().Provider.CreateQuery<City>(expr);
            var result = db.Citys.Where(Expression.Lambda<Func<City, bool>>(filter, param));
            list.DataSource = result.ToList();
            list.DisplayMember = "Name";




动态查询导航属性


实体关系如图:



如何拼接出 db.Citys.Where(x => x.Province.Name == "湖南省") 呢?,代码如下:

  1.             OscarEntities db = new OscarEntities(); 
  2.             IQueryable<City> cities = db.Citys; 
  3.             ParameterExpression param = Expression.Parameter(typeof(City), "c"); 
  4.             Expression left = Expression.Property(param, typeof(City).GetProperty("Province")); //先得到导航属性Province 
  5.             Expression leftproperty = Expression.Property(left, "Name"); //再得到Province.Name 
  6.             Expression right = Expression.Constant("湖南省"); 
  7.             Expression filter = Expression.Equal(leftproperty, right); 
  8.             var result = db.Citys.Where(Expression.Lambda<Func<City, bool>>(filter, param)); 
  9.             list.DataSource = result.ToList(); 
  10.             list.DisplayMember = "Name"
  11.  
  12. 网上的中文资料很少,我对着Expression.Property方法琢磨了老半天才整明白,写在这方便大家吧。 
  13.  
  14. 执行结果: 
            OscarEntities db = new OscarEntities();
            IQueryable<City> cities = db.Citys;
            ParameterExpression param = Expression.Parameter(typeof(City), "c");
            Expression left = Expression.Property(param, typeof(City).GetProperty("Province")); //先得到导航属性Province
            Expression leftproperty = Expression.Property(left, "Name"); //再得到Province.Name
            Expression right = Expression.Constant("湖南省");
            Expression filter = Expression.Equal(leftproperty, right);
            var result = db.Citys.Where(Expression.Lambda<Func<City, bool>>(filter, param));
            list.DataSource = result.ToList();
            list.DisplayMember = "Name";

网上的中文资料很少,我对着Expression.Property方法琢磨了老半天才整明白,写在这方便大家吧。

执行结果:


再贴上自己项目中用的方法

  1. public Expression GetProperty(Expression source, ParameterExpression para, string Name) 
  2.     string[] propertys = Name.Split('.'); 
  3.     if (source == null
  4.     { 
  5.         source = Expression.Property(para, typeof(City).GetProperty(propertys.First())); 
  6.     } 
  7.     else source = Expression.Property(source, propertys.First()); 
  8.     foreach (var item in propertys.Skip(1)) 
  9.     { 
  10.         source = GetProperty(source , para, item); 
  11.     } 
  12.     return source; 
        public Expression GetProperty(Expression source, ParameterExpression para, string Name)
        {
            string[] propertys = Name.Split('.');
            if (source == null)
            {
                source = Expression.Property(para, typeof(City).GetProperty(propertys.First()));
            }
            else source = Expression.Property(source, propertys.First());
            foreach (var item in propertys.Skip(1))
            {
                source = GetProperty(source , para, item);
            }
            return source;
        }

使用方法:

  1. ParameterExpression param = Expression.Parameter(typeof(City), "x"); 
  2. Expression left = GetProperty(null, param, "Province.Name"); //得到查询条件属性 
  3. Expression right = Expression.Constant("湖南省"); 
  4. Expression filter = Expression.Equal(left,right); 
            ParameterExpression param = Expression.Parameter(typeof(City), "x");
            Expression left = GetProperty(null, param, "Province.Name"); //得到查询条件属性
            Expression right = Expression.Constant("湖南省");
            Expression filter = Expression.Equal(left,right);



posted on 2012-10-22 13:02  swarb  阅读(111)  评论(0编辑  收藏  举报