将复杂查询写到查询配置文件--SOD框架的SQL-MAP技术简介

引言

今天看到一片热门的博客, .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配置文件,写个代码生成器,自动生成DAL层代码。 大名鼎鼎的 iBatis,MyBaits.Net 就是这样的功能,但它定义了一套复杂的规则,配置起来很复杂,项目可能80%的时间都在写查询配置,如果没有代码工具开发工作量很大的。

SQL-MAP--集中管理SQL查询

PDF.NET SOD框架SQL-MAP功能借鉴了iBaits的思想,但是大力简化它的配置并提供代码生成工具,可以自动化的完成DAL代码生成,下面是它的工作过程:

SOD框架提供了SqlMap配置文件管理器来管理和编写SQL配置文件,然后通过代码生成器生成DAL层代码,最后交给SODk框架执行。

编写SQL配置文件,如果通过上面说的配置工具来做,可以参考这篇文章:

PDF.NET之SQL-MAP使用图解

但这个程序太老,一直没有更新,工具的下载地址是:

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查询。

二、使用代码生成器

2.1 配置代码生成器

打开PDF.NET集成开发工具,选择菜单 “配置”--SQL-MAP代码生成器配置,出现下面的界面:

在编辑区域,鼠标右键菜单,启用用编辑,如果是第一次配置,请一定删除配置文件内的中文注释,否则配置文件格式无法识别。

这里主要配置SqlMap.config文件所在的完整路径,输出代码的目录,以及命名空间之类。

编辑完成,在编辑区的鼠标右键菜单上,启用“保存文件”的功能。

2.2 生成代码

如果上面配置正确,点击第二个工具栏的图标,就可以自动调用处 PDFCodeMaker.exe 程序,读取配置文件信息,自动生成DAL代码文件,如下图:

6

之后,我们添加刚才生成的DAL代码文件到项目中,如上图。

三、使用SqlMap配置文件

3.1 SqlMap配置文件的使用方式

SqlMap配置文件有2种使用方式,

  • 在AppSeting 里面指定文件路径
  • 嵌入到程序集文件

在本示例中,采用嵌入式编译的方式,这样SQL语句的安全性更高,但是不如作为独立文件使用修改方便。如下图:

这种方式编译,该资源文件的名字就是 “程序集默认名字空间.目录名字.文件名字” ,这里的例子是 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

四、运行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程序了:

设置一个断点,我们来看看 ”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下载使用。

时间: 2024-11-01 01:55:46

将复杂查询写到查询配置文件--SOD框架的SQL-MAP技术简介的相关文章

将复杂查询写到SQL配置文件--SOD框架的SQL-MAP技术简介

引言 今天看到一片热门的博客, .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 stu

Ajax写分页查询(实现不刷新页面)

要求: 获取数据库中大量的信息显示在页面上,必然要使用到分页查询: 若不使用Ajax,而是用其他的方法,肯定是要刷新页面的,用户体检很不好, 所以最好使用Ajax的方法写分页查询: 1.先来找一张数据很多的表吧! 一张简单的表 代码,引入jquery包: <script src="jquery-1.11.2.min.js"></script> 写一张表格,显示我们的代号跟名称: <table class="table table-striped&

python写一个查询接口

知识点: 1.flask_sqlalchemy查询: Flask-SQLAlchemy 在您的 Model 类上提供了 query 属性.当您访问它时,您会得到一个新的所有记录的查询对象.在使用 all() 或者 first() 发起查询之前可以使用方法 filter() 来过滤记录.如果您想要用主键查询的话,也可以使用 get() 2.flask视图 3.熟练sql查询 前置条件: 本地数据库创建一个测试库(test)&表(roles),该表只有2个字段,id,name,结构如图: 示例: 通

Django学习【第7篇】:Django之ORM跨表操作(聚合查询,分组查询,F和Q查询等)

django之跨表查询及添加记录 一:创建表 书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);     一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many). 创建一对一的关系:OneToOne("要绑定关系的表名") 创建一对多的关系:ForeignKey("要绑定关系的表名") 创建多对多的关系:ManyToMany(&qu

Django之ORM跨表操作(聚合查询,分组查询,F和Q查询等)

一:创建表 书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);     一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many). 创建一对一的关系:OneToOne("要绑定关系的表名") 创建一对多的关系:ForeignKey("要绑定关系的表名") 创建多对多的关系:ManyToMany("要绑定关系的表名"

Django框架08 /聚合查询、分组、F查询和Q查询、执行原生sql、设置 sql_mode

目录 Django框架08 /聚合查询.分组.F查询和Q查询.执行原生sql.设置 sql_mode 1.聚合查询 2.分组 3.F查询和Q查询 4.执行原生sql(了解) 5.展示sql的 6.设置 sql_mode Django框架08 /聚合查询.分组.F查询和Q查询.执行原生sql.设置 sql_mode 1.聚合查询 aggregate(*args, **kwargs) aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典.键的名称是聚合值

Mysql数据库理论基础之五--SELECT单多表查询、子查询、别名

一.简介 由MySQL AB公司开发,是最流行的开放源码SQL数据库管理系统,主要特点: 1.是一种数据库管理系统 2.是一种关联数据库管理系统 3.是一种开放源码软件,且有大量可用的共享MySQL软件 4.MySQL数据库服务器具有快速.可靠和易于使用的特点 5.MySQL服务器工作在客户端/服务器模式下,或嵌入式系统中 InnoDB存储引擎将InnoDB表保存在一个表空间内,该表空间可由数个文件创建.这样,表的大小就能超过单独文件的最大容量.表空间可包括原始磁盘分区,从而使得很大的表成为可能

第二十一章、使用查询表达式来查询内存中的数据

什么是语言集成查询(LINQ) 对从应用程序代码中查询数据的机制进行了“抽象”.这个功能称为“语言集成查询”(Language Integrated Query). LINQ的设计者大量借鉴了关系数据库管理系统(例如Microsoft SQL Server)的处理方式,将“数据库查询语句”与“数据在数据库中的内部格式”分隔开.LINQ的语法和语义和SQL很像,具有许多相同的优势.要查询的数据的内部结构发生改变后,不必修改查询代码.注意,虽然LINQ和SQL看起来很像,但LINQ更加灵活,而且能处

SQL编程之高级查询(子查询)以及注意事项

1.什么是子查询? 当一个查询是另一个查询的条件时,称之为子查询.子查询可以使用几个简单命令构造功能强大的复合命令.子查询最常用于SELECT-SQL命令的WHERE子句中.子查询是一个 SELECT 语句,它嵌套在一个 SELECT.SELECT...INTO 语句.INSERT...INTO 语句.DELETE 语句.或 UPDATE 语句或嵌套在另一子查询中. 语法:select ....from  表1  where  列1  > (子查询) 外面的查询成为父查询,圆括号嵌入的查询成为称