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中会抛如下异常:

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

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

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

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

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

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

动态查询导航属性

实体关系如图:

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

如何拼接出 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. 网上的中文资料很少,我对着Expression.Property方法琢磨了老半天才整明白,写在这方便大家吧。
  12. 执行结果:
  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. 网上的中文资料很少,我对着Expression.Property方法琢磨了老半天才整明白,写在这方便大家吧。
  12. 执行结果:
            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方法琢磨了老半天才整明白,写在这方便大家吧。 执行结果:

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

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

  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. }
  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);
上一篇:ngxin 添加模块


下一篇:MRO C3算法 super的运用