首页 > 编程语言 >给程序员准备的“蜜糍”--SOD框架简介

给程序员准备的“蜜糍”--SOD框架简介

时间:2023-07-12 23:14:45浏览次数:40  
标签:实体类 SOD 框架 -- 查询 程序员 SQL OQL

注:本文是SOD框架源码仓库的首页介绍,原文地址

一、框架介绍

1,SOD框架是什么?

以前有一个著名的国产化妆品“大宝SOD密”,SOD框架虽然跟它没有什么关系,但是名字的确受到它的启发,因为SOD框架就是给程序员准备的“蜜糍”(一种含有蜂蜜的糍粑),简单灵活且非常容易“上手”。

SOD框架LOG

SOD框架是一个全功能数据开发框架,框架的三大核心功能(SQL-MAP、ORM、Data Controls)代表三种数据开发模式(SQL开发模式/ORM开发模式/窗体控件开发模式),这三大功能名称的英文首字母缩写也是SOD框架名称的由来。SOD框架包含很多有用的功能组件,还包括多种企业级解决方案,以及相关的集成开发工具、图书和社区支持。

当你用它来开发复杂的企业级项目的时候,你会感觉“爱不释手”,因为不论你的团队是什么样子的,SOD框架总能给您提供以最简洁的方式实现最强大的功能,保证菜鸟级的程序员可以轻松看懂使用SOD框架编写的每一行代码,也能让资深程序员有一种“越野驾驶”的体验--对数据访问细节全方位的掌控能力!

SOD框架脱胎于PDF.NET框架,框架追求的目标就是简单与效率的平衡,体现在代码的精简、开发维护的简单与追求极致的运行效率。SOD框架目前运行在.NET平台,但它没有依赖于.NET框架很多独有的特性,这使得SOD框架在理论上有可能实现跨语言平台支持。

2,为什么需要SOD框架?

EF框架或大部分ORM框架的缺点就是SOD框架的优点, 因为SOD框架并不只是一个ORM框架。
ORM框架并不能解决所有的数据开发问题,如果试图这么做将大大增加ORM框架的复杂性和使用难度(比如用EF框架来做数据批量更新),所以这也是为什么很多开发人员更加喜欢Dapper这类“微型ORM”(或半ORM)的原因。

在企业级数据开发的时候,有时候使用其它一些手段能够起到更好的效果,这就要求框架要支持多种开发模式,支持更精准的操纵SQL查询,更灵活的对象关系映射(ORM),更直接的面向底层数据访问,或者更高层面的数据抽象,需要全方位的数据开发解决方案。SOD框架拥有超过15年的项目应用历史,相信它为你而生!

SOD框架包含SQL-MAP,ORM,DataControls三大子框架,但它却是一个非常轻量级的框架,也是一个企业级数据应用开发的解决方案。
了解更多,请看这里

SOD框架特别适合于以下类型的企业项目:

  1. 对数据操作安全有严格要求的金融行业;
  2. 对数据访问速度、内存和CPU资源有苛刻要求的互联网行业;
  3. 对需求常常变化,项目经常迭代,要求快速开发上线的项目;
  4. 对稳定性要求高,需要长期维护的企业级应用如MIS、ERP、MES等行业;
  5. 需要低成本开发,人员技能偏低的中小型项目。

因为足够简单,所以SOD框架是少数仍然支持 .NET 2.0的框架,当然,它也支持 .NET 3.x,.NET 4.x,.Net core 以及.NET 5/6等以上框架版本 。

3,功能特性

SOD框架包括以下功能:

3.1 核心三大功能 -(S,O,D):

  • SQL-MAP
    • XML SQL config and Map DAL --基于XML配置的SQL查询和数据访问层映射
    • SQL Map Entity --SQL语句映射为实体类
  • ORM
    • OQL(ORM Query Language) --ORM查询语言:OQL
    • Data Container --数据容器
    • Entity Indexer --实体类索引器访问
    • Table Map route Query --分表查询支持
    • Micro ORM --微型ORM
  • Data Controls
    • Consistent Data Froms --一致的数据窗体访问技术
    • WebForm Data Controls --Web窗体数据控件
    • WinForm Data Controls --Windows窗体数据控件

3.2 有用的功能组件:

Hot Use Cache             --热缓存(缓存最常用的数据)
Binary Serialization        --二进制序列化
Query Log                   --查询日志
Command Pipeline            --命令管道
Distributed Identification  --分布式ID

3.3 企业级解决方案:

MVVM (Web/WinForm)               --MVVM数据窗体
Memory Database                  --内存数据库
Transaction Log Data Replication --事务日志数据复制
Data Synchronization             --数据同步
Distributed transaction          --分布式事务
OData Client                     --OData 客户端

3.4 工具:

Integrated Development Tool     --集成开发工具,包括实体类生成、SQL-MAP代码自动生成和多种数据库访问工具。
Nuget support                   --Nuget 支持

4,源码和社区:

要了解更多,请看这篇文章:.NET ORM 的 “SOD蜜”--零基础入门篇
SOD框架企业级应用数据架构实战

或者参考框架作者编著的图书:SOD框架企业级应用数据架构实战,该书对SOD框架的企业级解决方案进行了详细的介绍。。

二、快速入门

1,准备工作

在开始工作之前,先建立一个控制台项目,然后在程序包管理控制台,添加SOD框架的Nuget 包引用:

Install-Package PDF.NET.SOD 

这样即可获取到最新的SOD框架包并且添加引用,然后,就可以开始下面的工作了。
已经建立好的当前Demo程序请看框架源码解决方案项目中的“SODTest”项目。

1.1,配置数据连接:

SOD框架默认使用应用程序配置文件中配置的最后一个数据连接配置,当然也可以不配置连接直接在程序中初始化数据连接对象。为了方便,我们在源码项目的app.config文件中,做如下数据访问连接配置:

<connectionStrings>
    <add name="local" 
       connectionString="Data Source=.;Initial Catalog=MyDB;Integrated Security=True" 
       providerName="SqlServer"/>
    <add name="local2"
       connectionString="Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=~/Database2.mdf;Integrated Security=True"
       providerName="SqlServer" />
  </connectionStrings>

providerName 是SOD框架的数据访问提供程序,PWMIS.Core.dll内置的可选简略名称有:

Access | SqlServer | Oracle | SqlCe | OleDb | Odbc

如果是其它的扩展程序集,那么providerName应该写成下面的形式:

providerName="<提供程序类全名称>,<提供程序类所在程序集>"

比如使用SOD封装过的Oracle官方的ADO.NET提供程序类:

providerName="PWMIS.DataProvider.Data.OracleDataAccess.Oracle,PWMIS.OracleClient"

在其它提供程序中,SOD框架提供了对【MySQL、Oracle、PostgreSQL、SQLite、达梦、人大金仓】等常见数据库的支持(扩展程序集),只要数据库提供了ADO.Net驱动程序,那么SOD框架经过简单包装即可保证支持。

在当前示例中使用的是名字为“local2”的数据连接,你可以修改成你实际的连接字符串,示例中使用的是SQLServer本地数据库文件,源码中已经包含了此文件,如果不能使用请重新创建一个。

1.2,实体类定义

SOD框架使用ORM功能并不需要先定义实体类,直接使用与数据表对应的接口类型即可开始查询。
下面定义一个用于数据访问的“用户表”接口和对应的实体类。

   public interface ITbUser
   {
       int ID { get; set; }
       string Name { get; set; }
       string LoginName { get; set; }
       string Password { get; set; }
       bool Sex { get; set; }
       DateTime BirthDate { get; set; }
   }   

   public class UserEntity : EntityBase, ITbUser
   {
       public UserEntity()
       {
           TableName = "TbUser";
           IdentityName = "ID";
           PrimaryKeys.Add("ID");
       }
       public int ID 
       {
           get { return getProperty<int>("ID"); }
           set { setProperty("ID", value); }
       }
       public string Name
       {
           get { return getProperty<string>("Name"); }
           set { setProperty("Name", value,100); } //长度 100
       }
       public string LoginName
       {
           get { return getProperty<string>("LoginName"); }
           set { setProperty("LoginName", value,50); }
       }
       public string Password
       {
           get { return getProperty<string>("Password"); }
           set { setProperty("Password", value,50); }
       }
       public bool Sex
       {
           get { return getProperty<bool>("Sex"); }
           set { setProperty("Sex", value); }
       }
       public DateTime BirthDate
       {
           get { return getProperty<DateTime>("BirthDate"); }
           set { setProperty("BirthDate", value); }
       }
   }

用同样的方式定义“订单”接口ISimpleOrder、ISimpleOrderItem 和相应的实体类SimpleOrderEntity、SimpleOrderItemEntity。有关这几个接口和类型的详细定义请参见项目源码。

元数据映射:

实体类的元数据包括映射的表名称、主外键、标识字段、属性映射的字段名称和字段类型、长度等。

在上面定义的实体类UserEntity中,它继承了SOD框架的实体类基类EntityBase,然后就可以在实体类的属性定义中使用
getProperty方法和setProperty方法,这两个方法都提供了“属性字段名”参数,它表示当前属性名和数据表字段名的映射关系。

在实体类构造函数中,TableName表示实体类映射的数据表名称,IdentityName表示映射的数据表标识字段名称,一般用于自增字段,PrimaryKeys表示实体类映射的主键字段,可以有多个字段来表示主键,例如联合主键。

动态映射:

SOD框架的实体类采用“动态元数据映射”,这些元数据都是可以在程序运行时进行修改,因此它与Entity Framework等其它ORM框架的实体类映射方式有很大不同。这个特点使得实体类的定义和元数据映射可以在一个类代码中完成,并且不依赖于.NET特性声明。这种动态性使得SOD框架可以脱离繁琐的数据库表元数据映射过程,简化数据访问配置,并且能够轻松的支持“分表、分库”访问。

逻辑映射(虚拟映射):

元数据的映射可以是“逻辑映射”,即映射一个数据表不存在的内容,例如指定要映射外键字段,但数据库可以没有物理的外键字段,或者指定一个虚拟的主键。也可以不做任何元数据映射,这样实体类可以作为一个类似的“字典”对象来使用,或者用于UI层数据对象。

动态实体类:

约定胜于配置。如果元数据全部采用默认映射,可以大大简化实体类的定义过程,直接采用接口类型来动态创建实体类和进行查询访问。

在默认映射的时候,通常将类型名称映射为表名称,属性名称映射为字段名称。如果是接口类型,映射表名称的时候会去掉接口名中第一个“I”字符。

例如接口类型 "IDbUser" 映射的表名称为 "DbUser"

下面是根据接口动态创建实体类的示例:

IDbUser user = EntityBuilder.CreateEntity<IDbUser>(); 

1.3,定义数据上下文

注意这是一个可选步骤,如果你不使用Code First开发模式的话。

在很多ORM框架中,数据上下文对象DbContext使用都很常见,但对于SOD框架并不是必须的,SOD框架崇尚简单直接的使用方式,有多种方式可以直接开始数据查询。如果你需要使用Code First开发模式,由程序自动创建数据表而不是先设计数据库表,可以使用SOD框架的数据上下文功能。

下面定义一个用于数据访问的简单数据上下文对象SimpleDbContext。

   public class SimpleDbContext : DbContext
    {
        public SimpleDbContext():base("local2")
        { 
        }

        protected override bool CheckAllTableExists()
        {
            CheckTableExists<UserEntity>();
            CheckTableExists<SimpleOrderEntity>();
            //创建表以后立即创建索引
            InitializeTable<SimpleOrderItemEntity>("CREATE INDEX [Idx_OrderID] On [{0}] ([OrderID])");
            return true;
        }
    }
 

在上面的代码中,SimpleDbContext使用名为“local2”的数据连接配置,它会在首次执行的时候调用CheckAllTableExists方法,检查表是否存在,如果不存在则创建实体类对应的数据表。
可以使用InitializeTable方法在表第一次创建完成以后执行表的初始化工作,比如创建索引。

2,数据访问辅助对象

AdoHelper对象是SOD框架的数据访问辅助对象,它是一个抽象数据访问对象,需要根据具体的数据库类型提供相应的数据访问提供程序。任何数据库的.NET驱动程序经过简单包装即可成为SOD框架的数据访问提供程序。
SOD框架内置的数据访问提供程序类型请参考本文【1.1 配置数据连接】的内容。

AdoHelper对象提供了各种数据访问方法,包括获取DataSet、DataReader以及执行数据的增删改、调用存储过程和多级事务查询等。
实例化一个AdoHelper对象可以通过MyDB类的多种方式来实现,也可以根据连接配置来动态创建,或者直接实例化一个SOD数据访问提供程序。下面的例子提供了三种方式来实例化AdoHelper对象:

//根据连接配置中的“连接名字”来创建,例如"local2"
AdoHelper db1 = MyDB.GetDBHelperByConnectionName("local2");
//根据连接配置中最后一个配置来创建
AdoHelper db2 = MyDB.GetDBHelper();
//直接实例化数据访问提供程序,例如SqlServer数据库
AdoHelper db3= SqlServer();

下面是使用AdoHelper的简单示例。

2.1,执行不返回值的查询

通过调用ExecuteNonQuery方法来实现,该方法返回本次执行受影响的行数的结果值。
下面是一个创建用户表的例子,创建的用户表在下面的示例中会使用到:

            AdoHelper db2 = AdoHelper.CreateHelper("local2");
            //异常处理示例
            string sql_createUser = @"
  Create table [TbUser](
    [ID] int identity primary key,
    [Name] nvarchar(100),
    [LoginName] nvarchar(50),
    [Password] varchar(50),
    [Sex] bit,
    [BirthDate] datetime
  )";
            try
            {
                db2.ExecuteNonQuery(sql_createUser);
                Console.WriteLine("表[TbUser] 创建成功!");
            }
            catch (PWMIS.DataProvider.Data.QueryException qe)
            {
                Console.WriteLine("SOD查询错误,错误原因:{0}", qe.InnerException.Message);
            }
            catch (Exception ex)
            {
                Console.WriteLine("错误:{0}", ex.Message);
            }

使用AdoHelper对象进行查询的时候,如果执行查询发生异常,使用异常处理代码可以捕获QueryException查询异常对象,
在该异常对象中可以查看详细的错误原因,以及执行查询相关的一些信息,如果SQL语句、执行参数等。

2.2,参数化查询

SOD框架认为保证数据访问的安全是框架最重要的目标,参数化查询是避免“SQL注入”最有效的手段。SOD框架对所有数据库都支持参数化查询,包括Access数据库等。
除了最基础的AdoHelper对象可以支持参数化查询,SQL-MAP功能也是支持参数化查询的。下面是使用参数化查询插入用户数据的例子:

            string sql_insert = "INSERT INTO [TbUser] ([Name],[LoginName],[Password],[Sex],[BirthDate]) VALUES(@Name,@LoginName,@Password,@Sex,@BirthDate)";
            IDataParameter[] paras = new IDataParameter[] {
                db2.GetParameter("Name","张三"),
                db2.GetParameter("LoginName","zhangsan"),
                db2.GetParameter("Password","888888"),
                db2.GetParameter("Sex",true),
                db2.GetParameter("BirthDate",new DateTime(1990,2,1))
            };

            int rc = db2.ExecuteNonQuery(sql_insert, CommandType.Text, paras);
            if (rc > 0)
                Console.WriteLine("插入数据成功!用户名:{0}", paras[0].Value);

AdoHelper对象的GetParameter方法有多个重载方法,可以满足参数化查询的各种需求,它返回的是当前数据库类型的查询参数对象,可以实现更多的参数化查询的细节控制,例如调用存储过程所需的查询参数。

2.3,微型ORM

微型ORM的特点是允许直接执行SQL语句查询,但是查询结果可以直接映射成为POCO类型或者实体类型,
相比较以前执行查询返回一个数据集(DataSet)而言,微型ORM即享受了直接编写SQL执行查询的灵活性,又得到了强类型对象使用的便利性,因此微型ORM很受开发人员欢迎。

SOD框架支持微型ORM功能,它允许你直接控制查询返回的DataReader对象,也可以将查询直接映射到一个强类型对象。下面的示例演示了通过微型ORM功能查询得到用户列表对象。

            string sql_query = "SELECT [ID],[Name],[Sex],[BirthDate] FROM [TbUser] WHERE [LoginName]={0}";
            var mapUsers = db2.ExecuteMapper(sql_query, "zhangsan")
                .MapToList(reader => new
                {
                    ID = reader.GetInt32(0),
                    Name = reader.GetString(1),
                    Sex = reader.GetBoolean(2),
                    BirthDate = reader.GetDateTime(3)
                });

            var userList = db2.QueryList<UserInfo>(sql_query, "zhangsan");

上面的示例演示了两者结果映射方式,使用AdoHelper对象的MapToList方法可以直接操作返回的DataReader对象,根据SQL语句中的字段顺序定制读取查询结果字段值,这种方式由于是面向底层Ado.NET的操作,因此查询具有很高的性能。
另外一种方式就是使用AdoHelper对象的QueryList方法,它直接将SQL查询结果映射为一个POCO对象。

上面的示例还演示了SOD的微型ORM查询使用的“参数化查询”方式,相比较于直接的参数化查询,这里只需要使用参数的占位符来表示参数,就像Console.WriteLine()方法使用的参数一样。例如上面的示例中查询的参数是字段LoginName对于的查询参数,参数值是“zhangsan”。

3,SQL-MAP简介

3.1,参数化查询的难题

参数化查询的SQL语句可以被数据库编译执行从而提高查询效率;参数化查询是在数据库完成 SQL 指令的编译后,才套用参数运行,因此就算参数中含有危害数据库的指令,也不会被数据库所运行,因此参数化查询提高了SQL执行的安全性。
虽然参数化查询有很多优点,但缺点是在开发上会增加代码编写量,另外由于参数化查询的SQL语句缺乏统一的标准,也会使得采用参数化查询的代码难以在不同数据库平台之间移植。请看下面的示例:

--Microsoft SQL Server

INSERT INTO myTable (c1, c2, c3, c4) VALUES (@c1, @c2, @c3, @c4)

--Microsoft Access

UPDATE myTable SET c1 = ?, c2 = ?, c3 = ? WHERE c4 = ?

--MySQL

UPDATE myTable SET c1 = ?c1, c2 = ?c2, c3 = ?c3 WHERE c4 = ?c4

--Oracle

UPDATE myTable SET c1 = :c1, c2 = :c2, c3 = :c3 WHERE c4 = :c4

--PostgreSQL

UPDATE myTable SET c1 = $1, c2 = $2, c3 = $3 WHERE c4 = $4

从上面不同数据库的SQL参数化查询的示例可以看到,不同数据库支持的参数查询的参数名写法是不同的,要求在参数名前面加不同的前缀符号(@/

标签:实体类,SOD,框架,--,查询,程序员,SQL,OQL
From: https://www.cnblogs.com/bluedoctor/p/17549123.html

相关文章

  • 就是个复述吧,去年九月份我确实找到工作了,今年5月底离职了,公司技术架构和项目太杂太老
    手写简易spring`packagecom.spring.utils;importcom.spring.BeanDefinition;importcom.spring.inteface.Autowried;importcom.spring.inteface.Component;importcom.spring.inteface.ComponentScan;importcom.spring.inteface.Scope;importcom.spring.service.UserS......
  • Java 继承、super() 关键字使用、super 和 this的区别
    Java继承、super()关键字使用、super和this的区别1.继承继承是子类使用extends关键字来继承父类获取相同的属性和方法,可以解决代码的复用性问题继承的基本思想:父类的构造器进行父类初始化,子类的构造器进行子类的初始化继承使用细节:子类在使用父类的方法或属性时,不能......
  • 读取jar包中资源目录失效
    目标文件: 请使用:InputStreamis=this.getClass().getResourceAsStream("/application.yml");这种方式原因其实是mvn的打包方式决定的,debug的时候getResource可以直接读取路径获取,打成jar则不行,当然如果你还在使用war包和tomcat,可以展开式部署,依然可以使用getResource......
  • 2023.7.12 鲜花
    昨天2023.7.11考的NOIDay1模拟,今天考Day2。个人感觉Day1比Day2可做多了。Day1T1很好做,然后T2今天调出来了,类似DFA建自动机,把所有可能的数处理出来,接着处理出所有状态的后继进行暴力数位DP匹配,可以获得90分高分。注意变量名取得正常一点,不要把乱七八糟......
  • 2023.7.12打卡
    2023.7.12(1)、今天考完科目二了,差一点点没过,然后从市里回来后学了会Java,看了会综艺,果然,恋爱还是看别人谈才有意思,晚上去打了会球,初中的老毛病又犯了,膝盖疼。(2)、明天学Java,记单词,看下《大道至简》,看辩论赛。(3)、做什么事都得认真对待。因为我去市里没带电脑,所以有几天没发博客。......
  • 魔法函数 __repr__() 和 __str__()的区别
    1'''2__repr__()和__str__()都是Python中的特殊方法,用于定义对象的字符串表示形式。它们之间的区别如下:31.__repr__(self):返回一个字符串,用于表示对象的“官方”字符串表示形式。这个字符串应该是可以用来重新创建对象的,并且应该尽可能准确和详细。4......
  • 第一章 机械运动
     1.1长度和时间的测量         ......
  • GPT-4镜像来了,体验核心能力
    1月份开始,chatgpt开始火上天了。但其实很多人都不知道它真正的能力和魅力在哪里。甚至有人不停的问他是男的女的,多大岁数,叫啥名字,然后问了几个无聊的闲聊问题后,觉得这个AI好像也没什么厉害的。正所谓是,提问者有多厉害,这个模型就会有多厉害。我把ChatGPT的核心能力归结为三点:......
  • “SecureCRT” 意外退出
    打开终端工具输入如下命令:xcode-select--install签名1、打开终端工具输入并执行如下命令:sudocodesign--force--deep--sign- 文件位置(直接将应用拖进去即可)(注意最后一个-与文件位置中间有一个空格)正常情况下只有一行提示,即成功:/文件位置:replacingexistingsignatur......
  • 服务器基础
    @目录第二章服务器基础1服务器介绍1.1什么是服务器1.2服务器发展历程1.3服务器的类型1.4服务器硬件介绍1.4.1服务器的硬件结构1.4.2CPU1.4.3内存1.4.4硬盘1.4.5RAID卡1.4.6网卡1.4.7电源和风扇模块2服务器关键技术2.1BMC介绍2.2BIOS2.2.1BIOS简介总结第二章服......