EntityFramework4.5使用Expression类创建动态查询及动态查询导航属性

创建动态查询

 

想在项目中实现一个灵活的动态查询类,参考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"; 
  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. 执行结果: 
  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; 
  1. public Expression GetProperty(Expression source, ParameterExpression para, string Name)  
  2. {  
  3.     string[] propertys = Name.Split('.');  
  4.     if (source == null)  
  5.     {  
  6.         source = Expression.Property(para, typeof(City).GetProperty(propertys.First()));  
  7.     }  
  8.     else source = Expression.Property(source, propertys.First());  
  9.     foreach (var item in propertys.Skip(1))  
  10.     {  
  11.         source = GetProperty(source , para, item);  
  12.     }  
  13.     return source;  
  14. }  
        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); 
  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); 
posted @ 2015-11-22 14:30  qq260250932  阅读(348)  评论(0编辑  收藏  举报