如何用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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏个人分享

前一天数据偏移至当日数据

客户画像项目中可能会遇到此类问题,因为客户画像要求的是对单个用户信息的查询。 但倘若以日周期为准,今日梳理的数据宽表中某个字段为null,但此类字段不能以nul...

15110
来自专栏更流畅、简洁的软件开发方式

分页解决方案 之 分页算法——Pager_SQL的思路和使用方法

      分页算法(也就是分页读取数据的时候使用的select 语句)面临两大难题:一个是不同的数据库使用的分页算法是不一样的(比如SQL Server 20...

27380
来自专栏友弟技术工作室

ElasticSearch入门实战1

12030
来自专栏烙馅饼喽的技术分享

本人有生以来的第一篇博客,嘿嘿,就发这个吧, 怎样在虚拟主机上使用Castle框架的ActiveRecord

        我在某个私人项目中使用了Castle 的 ActiveRecord.用起来那是真叫个爽,整个项目里楞是一句SQL语句都没有,嘿嘿。超级喜欢上了这...

27850
来自专栏技术翻译

23个有用的Elasticsearch示例查询

为了说明Elasticsearch中的不同查询类型,我们将使用以下字段搜索书籍文档的集合:标题,作者,摘要,发布日期和评论数。

86520
来自专栏小狼的世界

locale的详细解释

* Thu Sep 27 2001 Bernhard Rosenkraenzer 2.5-0.f.2

9640
来自专栏日常学python

一步一步教你如何用python操作mysql

这是日常学python的第九篇原创文章 首先祝大家新年快乐哈!学生的估计明天也要上课了,工作的估计早就去上班了,我也快要上课了,哈哈,新年这段时间一直没有写过文...

748130
来自专栏小白安全

SQL注入与原始的MD5散列(Leet More CTF 2010注入300)

注入300:使用原始MD5散列的SQL注入 昨天的CTF面临的一个挑战是看似不可能的SQL注入,价值300点。挑战的要点是提交一个密码给一个PHP脚本,在...

29540
来自专栏决胜机器学习

设计模式专题(二十) ——职责链模式

设计模式专题(二十)——职责链模式 (原创内容,转载请注明来源,谢谢) 一、概述 职责链模式(Chainof Responsibility),是使多个对象都有...

35690
来自专栏坚毅的PHP

HBase行锁与MVCC分析

四个部分分析: 案例场景 流程解析 0.94-0.96实现方案分析 模拟试验及分析 一、案例场景 转发微博 抱歉,此微博已被作者删除。查看帮助:http://...

53050

扫码关注云+社区

领取腾讯云代金券