引言
今天看到一片热门的博客, .NET高级工程师面试题之SQL篇 ,要求找出每一个系的最高分,并且按系编号,学生编号升序排列。这个查询比较复杂,也比较典型,自从用了ORM后,很久没有写过SQL语句了,于是我研究了下,自己也写了一个:
WITH cte1 as (
select stu.deptID,
D.depName,
stu.stuid ,
stu.stuName,
score_sum.AllScore
from dbo.Student stu
inner join (select stuid ,SUM(score) as AllScore from dbo.Score group by stuid) score_sum
on stu.stuid =score_sum.stuid
inner join dbo.Department D on stu.deptID= D.depID
)
select cte1.* from cte1
inner join (select deptID, max(AllScore) maxScore from cte1 group by deptID) M
on cte1.AllScore = M.maxScore and cte1.deptID=M.deptID
order by cte1.deptID,
cte1.stuid
我们工作中常常遇到类似的复杂查询,但常见的做法是把它写到BLL程序中,也有同学喜欢写在存储过程中,它有什么问题呢?
- 写到程序中,
- 容易养成拼接SQL的习惯,
- 并且SQL语句零散的分布到程序的各个地方,不好维护,
- 并有可能发生安全问题;
- 写到存储过程,
- 如果多了也不好维护,
- 并且程序调用不如直接调用SQL语句方便,
- 部署的时候还得部署这些存储过程,系统上线复杂的时候,常常忘记更新一两个存储过程。
除此之外,SQL语句不论写到程序中或者写在存储过程中,都有一个很大的缺点,程序无法跨数据库平台!
如果把所有的SQL语句都集中管理在一个配置文件中,那么程序编写和维护、发布都要方便很多,也容易跨数据库平台,甚至可以根据这个SQL配置文件,写个代码生成器,自动生成DAL层代码。 大名鼎鼎的 iBatis,MyBaits.Net 就是这样的功能,但它定义了一套复杂的规则,配置起来很复杂,项目可能80%的时间都在写查询配置,如果没有代码工具开发工作量很大的。
当然,与MyBatis不一样之处,SOD框架并不主张将项目的查询都用SQL写到SqlMap文件,建议大家仅将复杂的SQL查询写到SqlMap配置文件,一般项目这类复杂查询也就20%左右,而对于80%的一般查询,使用ORM即可,框架同时支持ORM与SqlMap技术,这是SOD框架的一大特点!
SQL-MAP--集中管理SQL查询
PDF.NET SOD框架的SQL-MAP功能借鉴了iBaits的思想,但是大力简化它的配置并提供代码生成工具,可以自动化的完成DAL代码生成,下面是它的工作过程:
SOD框架提供了SqlMap配置文件管理器来管理和编写SQL配置文件,然后通过代码生成器生成DAL层代码,最后交给SODk框架执行。
编写SQL配置文件,如果通过上面说的配置工具来做,可以参考这篇文章:
但这个程序太老,一直没有更新,工具的下载地址是:
http://ft.codeplex.com/releases/view/65308
工具包含在这个“集成开发工具” 内,通过菜单或者图标即可操作。下面是集成开发工具打开数据库并执行本文的查询的界面:
SQL-MAP配置管理工具不太好用,初学者学习概念可以试一试,但是要想熟练应用,推荐使用VS来写这个SQL配置文件更方便。本文将向大家详细介绍这个过程。
一、编写SQL-MAP配置文件
1.1,建立SQL-MAP应用项目
如下图所示,新建一个 SqlMapDemo项目,在它里面先添加一个XML文件,文件命名为 SqlMap.config ,然后,找到上面的“集成开发工具”的安装目录,添加 SqlMap.xsd 文件。该文件很重要,它是我们在VS里面编写XML文件能够有 智能提示 的关键。
添加了这个XSD文件到项目后,还需要把下面的内容
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="SqlMap.xsd"
注意:有关此详细内容,请参见《PDF.NET(PWMIS数据开发框架)之SQL-MAP目标和规范》。
1.2 使用XML智能提示
将上面的内容添加到刚才的SqlMap.config 文件中,这样,输入尖括号,或者输入空格,智能提示内容就出来,如下所示:
这是添加完整的SqlMap.config 文件,该文件完全手写,在智能提示的帮助下,编写还是很方便的。请注意配置文件内各个节点属性的内容,详细内容请看上面链接的文件。注意,这里要用 CDATA 来写SQL查询。
注意:如果要执行获得结果集的查询,需要在Sql-Map文件的命令节点里面使用 Select 节点,并且需要指明 ResultClass 的类型,它有下面几种可选值:
- ValueType --结果为值对象,比如Int,String之类的查询单值结果
- DataSet --数据集,默认
- EntityObject --单个实体类对象
- EntityList --实体类列表
注意:如果指定 ResultClass="EntityObject" / ResultClass="EntityList" ,那么需要同时申明 ResultMap 属性,表示结果要映射到的具体类型,比如:
ResultClass="EntityObject" ResultMap="XXXNameSpace.YYYEntityClass"
有关此详细内容,请参见《PDF.NET(PWMIS数据开发框架)之SQL-MAP目标和规范》。
二、使用代码生成器
2.1 配置代码生成器
打开PDF.NET集成开发工具,选择菜单 “配置”--SQL-MAP代码生成器配置,出现下面的界面:
在编辑区域,鼠标右键菜单,启用用编辑,如果是第一次配置,请一定删除配置文件内的中文注释,否则配置文件格式无法识别。
这里主要配置SqlMap.config文件所在的完整路径,输出代码的目录,以及命名空间之类。
编辑完成,在编辑区的鼠标右键菜单上,启用“保存文件”的功能。
2.2 生成代码
如果上面配置正确,点击第二个工具栏的图标,就可以自动调用处 PDFCodeMaker.exe 程序,读取配置文件信息,自动生成DAL代码文件,如下图:
6
之后,我们添加刚才生成的DAL代码文件到项目中,如上图。
三、使用SqlMap配置文件
3.1 SqlMap配置文件的使用方式
SqlMap配置文件有2种使用方式,
- 在应用程序配置文件的AppSeting 配置节里面指定文件路径
- 嵌入到程序集文件作为资源文件使用
在本示例中,采用嵌入式编译的方式,这样SQL语句的安全性更高,并且支持一个项目中使用多个SqlMap配置文件,但是不如作为独立文件使用修改方便。如下图:
这种方式编译,该资源文件的名字就是 “程序集默认名字空间.目录名字.文件名字” ,这里的例子是 SqlMapDemo.SqlMap.config ,由于在跟目录下面,没有目录名字。
注意,要正确使用嵌入式SQL配置文件,还必须在该文件中指出"嵌入文件的程序集名称,资源文件名字“,如本例如下图红色边框标记的部分所示:
SqMap.config 文件修改完成后,在此启动 PDFCodeMaker.exe 程序,重新生成DAL文件,如下所示,增加了签入式文件的设置:
3.2 生成SqlMapDAL文件
检查发现,DAL类文件的名字空间不正确,这里修改下配置文件的 RootNameSpace 部分,如下图:
重新生成DAL类文件,我们看看最后生成的SqlMapDAL类的内容:
//使用该程序前请先引用程序集:PWMIS.Core,并且下面定义的名称空间前缀不要使用PWMIS,更多信息,请查看 http://www.pwmis.com/sqlmap
// ========================================================================
// Copyright(c) 2008-2010 公司名称, All Rights Reserved.
// ========================================================================
using System;
using System.Data;
using System.Collections.Generic;
using PWMIS.DataMap.SqlMap;
using PWMIS.DataMap.Entity;
using PWMIS.Common; namespace SqlMapDemo.SqlMapDAL
{
/// <summary>
/// 文件名:TestSqlMapClass.cs
/// 类 名:TestSqlMapClass
/// 版 本:1.0
/// 创建时间:2015/5/12 17:16:32
/// 用途描述:SQL-MAP示例测试程序
/// 其它信息:该文件由 PDF.NET Code Maker 自动生成,修改前请先备份!
/// </summary>
public partial class TestSqlMapClass
: DBMapper
{
/// <summary>
/// 默认构造函数
/// </summary>
public TestSqlMapClass()
{
Mapper.CommandClassName = "TestGroup";
//CurrentDataBase.DataBaseType=DataBase.enumDataBaseType.SqlServer;
Mapper.EmbedAssemblySource="SqlMapDemo,SqlMapDemo.SqlMap.config";//SQL-MAP文件嵌入的程序集名称和资源名称,如果有多个SQL-MAP文件建议在此指明。
} /// <summary>
/// 找出每一个系的最高分,并且按系编号,学生编号升序排列
/// </summary>
/// <returns></returns>
public DataSet QueryStudentSores( )
{
//获取命令信息
CommandInfo cmdInfo=Mapper.GetCommandInfo("QueryStudentSores");
//执行查询
return CurrentDataBase.ExecuteDataSet(CurrentDataBase.ConnectionString, cmdInfo.CommandType, cmdInfo.CommandText ,null);
//
}//End Function }//End Class }//End NameSpace
SqlMapDemo.SqlMapDAL
3.3 团队开发
团队开发常常涉及到文件修改冲突,SqlMap配置文件也会遇到,如果大家不去修改同一个Command配置,用源代码管理器的自动合并功能是没有问题的。
如果是独占式签出管理,那么一个开发人员使用SqlMap文件,另外一个就只有等待了,但框架提供了变通的方式来解决这个问题。
- 按功能模块划分DAL程序集,每个DAL程序集一个SqlMap.config文件,选择嵌入式编译;
- 在一个DAL程序项目上建立多个SqlMap.config文件,选择嵌入式编译 。
注意:建议每一个开发人员负责一个SqlMap.config文件的管理,然后各自配置自己的PDFCodeMaker.exe.config
3.4 切换数据库
在同一个SqlMap.config 文件里面添加新的 <Script Type="" 节点,比如Oracle ,然后将原来数据库类型的SQL查询改写成当前类型的SQL查询语句 ,程序会根据DBMapper的AdoHelper的实际类型自动选择正确的<Script Type="" 节点,从而完成数据库切换,实现你的应用系统跨数据库的功能。
另外,也可以另外建立一个SqlMap.config 文件,里面专门写新的数据库下面的SQL语句,我们以前一个银行的项目,就是这样从SqlServer移植到PostgreSql的。
四、运行SQL-MAP程序
4.1 配置连接字符串
SQL-MAP DAL类程序仍然通过AdoHelper 对象来执行,这里添加一个应用程序配置文件:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name ="default" connectionString="Data Source=.;Initial Catalog=TestDB;Integrated Security=True" providerName="SqlServer"/>
</connectionStrings>
</configuration>
4.2 运行程序
然后,就可以写如下的代码来测试SQL-MAP程序了:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("PDF.NET SOD框架 SqlMap示例程序--2015.5.12-------");
Console.WriteLine("http://www.pwmis.com/sqlmap ---------"); SqlMapDemo.SqlMapDAL.TestSqlMapClass test = new SqlMapDAL.TestSqlMapClass(); //AdoHelper db = new SqlServer();
//取最后一个连接配置
AdoHelper db = MyDB.GetDBHelper();
//SQL-MAP DAL 默认也会取最后一个连接配置,所以下面一行代码可以注释
//test.CurrentDataBase = db;
DataSet data = test.QueryStudentSores(); Console.WriteLine("查询到记录数量:{0}",data.Tables[0].Rows.Count);
Console.WriteLine("测试完成。");
Console.Read();
}
}
结果运行如下:
设置一个断点,我们来看看 ”SQL-MAP DAL对象“的Mapper对象有哪些内容:
在及时窗口输入 test.Mapper ,回车,就可看到上面的内容了。这里显示了刚才配置的SQL-MAP嵌入式文件的位置和文件独特的路径:SqlMapFile 属性。
下面是详细的结果:
test.Mapper
{PWMIS.DataMap.SqlMap.SqlMapper}
_CommandClassName: "TestGroup"
_DataBase: {PWMIS.DataProvider.Data.SqlServer}
_dataBaseType: SqlServer
_embedAssemblySource: "SqlMapDemo,SqlMapDemo.SqlMap.config"
_ParaChar: "@"
_ParamsMap: {PWMIS.Common.ParamMapType[0]}
_ParasLenth: 0
_ResultClass: ValueType
_ResultMap: ""
_SqlMapFile: "@R://SqlMapDemo,SqlMapDemo.SqlMap.config"
结语
测试完全正确,使用 SOD框架的SQL-MAP 技术是不是很简单?
后续都只需要修改下文件里面的SQL语句就行了,
一次配置,一键生成!
这就是,SOD框架的SQL-MAP 技术的特点!结合SOD框架的ORM功能,它完全可以代替MyBatis.Net 。
感谢大家关注PDF.NET SOD框架,这是一个开源免费的框架,详细信息请看官网 http://www.pwmis.com/sqlmap
框架开源项目地址:http://pwmis.codeplex.com ,本项目示例代码已经签入到codeplex 上,大家可以通过SVN下载使用。
本篇程序已经提供了独立的下载: Sql-Map Demo
将复杂查询写到SQL配置文件--SOD框架的SQL-MAP技术简介的更多相关文章
-
Git.Framework 框架随手记--SQL配置文件的使用
前面几篇文章讲到了如何使用框架进行简单结构的增删改查操作,由于个人能力有限在对于复杂的SQL操作面前也是无能为力,只能自己动手来写SQL语句.在Git.Framework中提供了一个公共的接口来直接操 ...
-
【Mybatis】MyBatis之Sql配置文件的使用(四)
上一章[Mybatis]MyBatis对表执行CRUD操作(三),已经讲了基本操作,本章介绍Sql配置文件中常用功能 1.插入返回主键 2.参数值的获取方式 3.resultMap使用 插入返回主键 ...
-
[转]如何写出高效能TSQL -深入浅出SQL Server Relational Engine (含 SQL 2014 in-memory Engine)
[转]如何写出高效能TSQL -深入浅出SQL Server Relational Engine (含 SQL 2014 in-memory Engine) http://blogs.technet. ...
-
一对一关联查询时使用relation连贯操作查询后,调用getLastSql()方法输出的sql语句
如题: 一对一关联查询时使用relation连贯操作查询后,调用getLastSql()方法输出的sql语句不是一条关联查询语句. 例如: $list = $db->relation(true) ...
-
(转载)将DELPHI数据库连接写进INI配置文件中
将DELPHI数据库连接写进INI配置文件中 procedure TDM.DataModuleCreate(Sender: TObject); var piececonfg:Tinifile; pat ...
-
用游标实现查询当前服务器所有数据库所有表的SQL
declare @name varchar(100) DECLARE My_Cursor CURSOR --定义游标 FOR (SELECT Name FROM Master..SysDatabase ...
-
图解“管道过滤器模式”应用实例:SOD框架的命令执行管道
管道和过滤器 管道和过滤器是八种体系结构模式之一,这八种体系结构模式是:层.管道和过滤器.黑板.代理者.模型-视图-控制器(MVC) 表示-抽象-控制(PAC).微核.映像. 管道和过滤器适用于需要渐 ...
-
DataSet的灵活,实体类的方便,DTO的效率:SOD框架的数据容器,打造最适合DDD的ORM框架
引言:DDD的困惑 最近,我看到园子里面有位朋友的一篇博客 <领域驱动设计系列(一):为何要领域驱动设计? >文章中有下面一段话,对DDD使用产生的疑问: •没有正确的使用ORM, 导致数 ...
-
Oracle 免费的数据库--Database 快捷版 11g 安装使用与";SOD框架";对Oracle的CodeFirst支持
一.Oracle XE 数据库与连接工具安装使用 Oracle数据库历来以价格昂贵出名,当然贵有贵的道理,成为一个Oracle DBA也是令人羡慕的事情,如果程序员熟悉Oracle使用也有机会接触到大 ...
随机推荐
-
tp中ueditor编辑器的使用
1/引入三个文件 <script type="text/javascript" charset="utf-8" src="{$Think.con ...
-
new和alloc init的区别
背景说明,new是较为老式的写法,后来发现只有一个new不好使,才引入了alloc和init这种写 法,保留new一是向后兼容,二是很多时候是一种更简单的写法.其实是一样的,new在内部调用 的all ...
-
JPush 极光推送 消息推送 实例
简介 官网:https://www.jpush.cn/ 极光推送(JPush)是一个端到端的推送服务,使得服务器端消息能够及时地推送到终端用户手机上,让开发者积极地保持与用户的连接,从而提高用户活跃度 ...
-
SSH框架之hibernate《二》
Hibernate第二天 一.hibernate的持久化类和对象标识符 1.1持久化类的编写规范 1.1.1什么是持久化类: ...
-
SELinux入门简介
操作系统有两类访问控制:自主访问控制(DAC)和强制访问控制(MAC).标准Linux安全是一种DAC,SELinux为Linux增加了一个灵活的和可配置的的MAC. 进程启动时所拥有的权限就是运行此 ...
-
Python笔记(三)继承和多态、动态语言
一.继承 先定义一个A类 class A(object): def fun(self): print "Run A fun()" 在定义一个B类 class B(A): pass ...
-
mysql distinct 用法详解及优化
本事例实验用表task,结构如下 MySQL> desc task; +-------------+------------+------+-----+-------------------+- ...
-
linux命令(43):awk的使用技巧
AWK是一种处理文本文件的语言,是一个强大的文本分析工具. 之所以叫AWK是因为其取了三位创始人 Alfred Aho,Peter Weinberger, 和 Brian Kernighan 的Fam ...
-
ES(5): ES Cluster modules settings
ES cluster 提供了针对不同模块的参数设置,可通过修改集群上各个节点的elasticsearch.yml文件,也可在集群运行时通过api接口来更新(https://www.elastic.co ...
-
Linux 之rsyslog+LogAnalyzer 日志收集系统
一.LogAnalyzer介绍 LogAnalyzer工具提供了一个易于使用,功能强大的前端,用于搜索,查看和分析网络活动数据,包括系统日志,事件日志和其他许多日志源.由于它只是将数据展示到我们用户的 ...