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



  • 相关阅读:
    SQL的四种连接-左外连接、右外连接、内连接、全连接
    查看Linux下端口占用情况的命令
    linux的命令(1)
    xsheell的下载安装初级使用
    日交易,根据权重分配流量的算法,根据权重和交易笔数
    根据权重挑选通道的简单算法
    Java中的String与常量池
    JAVA虚拟机内存分配与回收机制
    JVM 内部运行线程介绍
    AspectJ切入点语法详解
  • 原文地址:https://www.cnblogs.com/swarb/p/9924379.html
Copyright © 2020-2023  润新知