zoukankan      html  css  js  c++  java
  • 使用操作符重载,生成ORM实体类的SQL条件语句

    ORM框架的一个不可或缺的功能就是根据实体类,生成操作数据库的SQL语句,这其中,最难处理的就是那些复杂的SQL条件比较语句。比如,有下面这样一个SQL语句:

    SELECT [id],[BankCode],[CityCode],[FundCode],[FundName],[FundReviews],[EndDagte],[addDate]
     FROM [FundReviews]
        WHERE  ( 
                 ([CityCode]=@CP1 OR [BankCode]=@CP2)  
            AND  ([FundCode]=@CP3 OR [BankCode]=@CP4
               )

    这个复杂的查询条件由两个OR子条件最后组合成一个AND 条件的,因此它有3组条件:

    1:[CityCode]=@CP1 OR [BankCode]=@CP2;

    2:[FundCode]=@CP3 OR [BankCode]=@CP4;

    3:1 AND 2 ;

    而条件1其实就是 Condition1 OR Condition2,这又是一个条件组合。

    我们发现,尽管SQL的条件语句可能很复杂,但这些条件却是由一些子条件组合成的,或者说由一组条件组合成一个新的条件,大家想想,这是不是典型的“组合模式”阿?

     

    在PDF.NET框架的ORM组件中,有一个专门处理条件的对象OQLCompare ,它就是根据“组合模式”设计的,我们来看看怎么由它来构造这个查询条件:

    1,采用AND,OR重载:

     

    FundReviews p = new FundReviews();//实例化一个实体类
    OQL q = new OQL(p);               //实例化一个OQL对象
    Console.WriteLine("OQLCompare 复杂比较条件表达式测试---------");

    OQLCompare cmp = new OQLCompare(p);
    OQLCompare cmpResult = (cmp.Comparer(p.CityCode, OQLCompare.CompareType.Equal, "021")
                    | cmp.Comparer(p.BankCode, OQLCompare.CompareType.Equal, "008"))
                    & (cmp.Comparer(p.FundCode, OQLCompare.CompareType.Equal, "KF008")
                    | cmp.Comparer(p.BankCode, OQLCompare.CompareType.Equal, "008"));
               

    q.Select().Where(cmpResult);

    Console.WriteLine("SQL=" + q.ToString());

    在OQL中,采用了类似SQL的语法,也是

     

    Select([属性列表]).Where([条件表达式]).OrderBy([排序字段]).GroupBy([分组字段]

    其中[条件表达式]就可以使用OQLCompare对象来构造。由于OQLCompare对象Comparer函数返回的仍然是一个OQLCompare对象,所以可以利用这个特点,采用组合模式,构造出非常复杂的SQL条件语句。

     

    我们看到OQL采用了类似函数式的语法风格,但在[条件表达式]的构造过程中,还是显得很冗长,我们可以继续对OQLCompare对象进行重构:

         /// <summary>
            
    /// 设置等于某个实体属性的比较条件
            
    /// </summary>
            
    /// <param name="compare">当前实体比较对象</param>
            
    /// <param name="Value">要比较的值</param>
            
    /// <returns>构造的实体比较对象</returns>
            public static OQLCompare operator ==(OQLCompare compare, object Value)
            {
                return BuildOperator(compare, Value, " = ");
            }

            /// <summary>
            
    /// 设置不等于某个实体属性的比较条件
            
    /// </summary>
            
    /// <param name="compare">当前实体比较对象</param>
            
    /// <param name="Value">要比较的值</param>
            
    /// <returns>构造的实体比较对象</returns>
            public static OQLCompare operator !=(OQLCompare compare, object Value)
            {
                return BuildOperator(compare, Value, " <> ");
            }

         /// <summary>
            
    /// 根据实体对象的属性,获取新的条件比较对象
            
    /// </summary>
            
    /// <param name="field"></param>
            
    /// <returns></returns>
            public OQLCompare Property(object field)
            {
                OQLCompare cmp = new OQLCompare();
                cmp.CompareString = this.currPropName ;
                return cmp;
            }

            private static OQLCompare BuildOperator(OQLCompare compare, object Value,string operatorString)
            {
                string paraName = compare.GetNewParameterName();
                compare.CompareString += operatorString + paraName;
                compare.compareValueList.Add(paraName.Substring(1), Value);
                return compare;
            }

    我们可以采用类似的方式,继续实现 >=,>,<=,< 等SQL条件比较符号的重载,这里就不一一举例了,我们来看新的使用方式:

    2,采用SQL比较符号的重载:

    //对象 p 为实体类
    OQLCompare cmp2 = new OQLCompare(p);
    OQLCompare cmpResult2 = 
                   ( cmp2.Property(p.CityCode) == "021"  | cmp2.Property(p.BankCode) == "008")
                   &  
                   ( cmp2.Property(p.FundCode) == "KF008"| cmp2.Property(p.BankCode) == "008");


    q.ReSet();//重新初始化OQL
    q.Select().Where(cmpResult2);

    Console.WriteLine("操作符重载 SQL=" + q.ToString());

    现在这个SQL条件的构造过程是不是清晰多了?这就是操作符重载的魅力:)

    3,使用Equal方法,简化相等比较

    直接看下面的代码,功能跟上面的例子一样:

    //对象 p 为实体类
    OQLCompare cmp2 = new OQLCompare(p);
    OQLCompare cmpResult2 = 
                   ( cmp2.Equal(p.CityCode,"021")    | cmp2.Equal(p.BankCode,"008")  )
                   &  
                   ( cmp2.Equal(p.FundCode,"KF008")  | cmp2.Equal(p.BankCode,"008")  );

    q.ReSet();//重新初始化OQL

    q.Select().Where(cmpResult2);

    Console.WriteLine("操作符重载 SQL=" + q.ToString());

    从性能上来说,这种方式效率稍高,因为它是函数式的处理方式,更直接。

    -------------------------------------------------------------------------

    注:本文介绍的这个OQL特性仅在PDF.NET Ver 4.3版本受支持,但之前的版本参照本文说的方法加以改进,也可以使用。有关PDF.NET的版本信息,请看官网介绍:
    http://www.pwmis.com/sqlmap
    有关PDF.NET的开源信息,请参看我的博客文章:

    节前送礼:PDF.NET(PWMIS数据开发框架)V3.0版开源

     

     

  • 相关阅读:
    代码—五天前是星期几
    随手笔记-日期
    建造曲线记忆表格
    2017-5-10随手记
    java-web——第一课 tomcat
    复习
    Leetcode 24. Swap Nodes in Pairs(详细图解一看就会)
    这可能是最详细的解析HTTP走私攻击的文章
    使用grub2引导进入Linux或Window系统
    ACM集训第一次积分赛赛前复习+day4
  • 原文地址:https://www.cnblogs.com/bluedoctor/p/2369256.html
Copyright © 2011-2022 走看看