zoukankan      html  css  js  c++  java
  • 如何用ORM支持SQL语句的CASE WHEN?

    OQL如何支持CASE WHEN?

    今天,一个朋友问我,OQL可否支持CASE WHEN语句?他给的示例SQL如下:

    select HName,case when IsEnable=1 then '启用' else '停用' from tb_User

    OQL是SOD框架ORM查询语言,它类似Linq,但是它诞生的历史比Linq早,并且更加接近SQL语法。所以,对SOD框架而言,对应ORM如何支持CASE WHEN,就等于是问OQL如何支持CASE WHEN了。

    这个问题已经不止这一个朋友来问我了,我想了下,还是把这个问题的解决写一篇博客,给大家一种新的解决方案。
    注意“新的方案”这个提法,我是不打算让OQL支持CASE WHEN这个特性的,为何要这样做呢?

    1. OQL只解决 80%的普通查询,其它复杂的查询,应该依托于其它技术,否则会增加OQL的复杂性;
    2. 复杂的查询,可以借助于SOD框架的SQL-MAP技术,将SQL语句写在SqlMap.config文件中;
    3. 可以采用数据库视图或者表的计算列,但有些数据库可能不支持计算列;


    前面3种原因,第2,3条方法也可以看做是此问题的解决方案,但是它们都需要增加更多的工作量,如果OQL能够直接支持还是更方便些,所以,我今天在这里给大家第4种解决方案:

    实体类的计算属性

    废话不多说,先直接看代码:

    public class User:EntityBase
    {
      public User()
      {
          TableName="tb_User";   
      }
    
      public string HName{
        get{return getProperty<string>("HName");}
        set{setProperty<string>("HName",value,50);}
      }
    
      public bool IsEnable{
        get{return getProperty<bool>("IsEnable");}
        set{setProperty<bool>("IsEnable",value);}
      }
      
      public string IsEnableDescrition
      {
         get{
            return IsEnable?"启用":"停用"
         }
       }
    
    }

    在这里,HName,IsEnable 这样的属性,SOD框架称为“持久化属性”,因为它MAP了Tb_User表的字段IsEnable ,该字段称为“持久化属性字段”。

    持久化属性的get,set方法采用了SOD实体类特殊的方法 setProperty,getProperty 构造,所以属性IsEnableDescription 它不是持久化属性,但是它利用了IsEnable这个持久化属性,对持久化属性进行“计算”,因此,我们这里称呼这样的属性为实体类的“计算属性”。

    大家看看,这个“计算属性”是不是很好的起到了 SQL的CASE WHEN效果?

    只要忘记了数据库,不要遇到问题就去想如何用SQL语句解决,是不是思路豁然开朗?

    使用“计算属性”来支持CASE WHEN效果

    前面说过,实体类的“计算属性”本质上不是一个“持久化属性”,它是对持久化属性的计算处理,原理上非常类似SQLServer表上面的计算列。
    因此,在SOD框架上使用“计算属性”,有一个必须注意的原则:“计算属性”不可以出现在OQL语句中。

    具体举例来说,应该像下面的样子来使用包含计算列的实体类:

    User user=new User(){ HName="张三"};
    var q=OQL.From(user)
      .Select(user.HName,user.IsEnable)
      .Where(user.HName)
    .END;
    
    User user2= EntityQuery<User>.QueryObject(q);
    string isEnableDesction =user2.isEnableDesction;

    使用“ViewModel”来支持CASE WHEN效果


    如果再仔细看看开篇的这个SQL语句,我们发现这种写法常常跟我们的界面查询有关,也就是这个查询要将原来的结果进行一下加工,以方便界面元素使用。对应这种需求,我们通常想到的办法是写一个ViewModel来定制这个查询结果。实际上,前面那个SOD实体类就是一种ViewModel,但它是基于实体类上的ViewModel,之外,SOD也支持直接将查询结果映射到ViewModel。

    因此,前面的实体类需要改写成下面这个样子:

    public class User:EntityBase
    {
      public User()
      {
          TableName="tb_User";   
      }
    
      public string HName{
        get{return getProperty<string>("HName");}
        set{setProperty<string>("HName",value,50);}
      }
    
      public bool IsEnable{
        get{return getProperty<bool>("IsEnable");}
        set{setProperty<bool>("IsEnable",value);}
      }
      
    }

    这里去掉了前面的“计算列属性”,它将用一个匿名类型的属性来代替:

    User user=new User(){ HName="张三"};
    var q=OQL.From(user)
        .Select()
        .Where(user.HName)
    .END;
    
     PWMIS.DataProvider.Data.AdoHelper db = PWMIS.DataProvider.Adapter.MyDB.GetDBHelper();
     EntityContainer ec = new EntityContainer(q, db);
     var list = ec.MapToList()(()=> return new
         {
            HName = user.HName,
            IsEnableDescription =user.IsEnable?"启用":"停用"
         });

    这里的匿名类型中包含了 IsEnableDescription 一个属性,同时我们的OQL查询也不再需要在Select里面指定查询的属性,而是推迟到MapToList方法里面。

    上面这种查询方式,同样支持了我们标题的需求,可见,SOD对一个查询问题,往往能够提供多种解决方案,“条条道路通罗马”,这正是SOD的设计谏言

    ---------------分界线--------------------------------------------------------------------------------

    有关上面SOD框架查询使用的入门介绍,大家可以参考《.NET ORM 的 “SOD蜜”--零基础入门篇 》

    感谢大家对SOD框架一直以来的支持,更多信息,请参考 PDF.NET SOD 开源框架红包派送活动 && 新手快速入门指引

    开源项目需要大家更多的支持,SOD开源项目网站:http://pwmis.codeplex.com

  • 相关阅读:
    Android 主题theme说明 摘记
    Android开发 去掉标题栏方法 摘记
    安卓项目五子棋代码详解(二)
    关于 ake sure class name exists, is public, and has an empty constructor that is public
    百度地图3.0实现图文并茂的覆盖物
    android onSaveInstanceState()及其配对方法。
    关于集成科大讯飞语音识别的 一个问题总结
    android 关于 webview 控制其它view的显示 以及更改view数据失败的问题总结
    C# 解析 json Newtonsoft果然强大,代码写的真好
    c#数据类型 与sql的对应关系 以及 取值范围
  • 原文地址:https://www.cnblogs.com/bluedoctor/p/5639856.html
Copyright © 2011-2022 走看看