HiSql 源码(github) https://github.com/tansar/HiSql
git clone https://github.com/tansar/HiSql.git
数据插入插入
HiSql 提供了丰富多样的数据插入方式,通过极致的性能优化目前在常用的ORM中名列前茅
单表数据插入
性能测试结果
插入记录数 | hisql(耗时) | sqlsugar(耗时) | freesql(耗时) |
---|---|---|---|
5条 | 0.0107秒 |
0.0312秒 |
0.02675秒 |
10条 | 0.0111秒 |
0.0307秒 |
0.0271秒 |
50条 | 0.0174秒 |
0.0364秒 |
0.0430秒 |
100条 | 0.0281秒 |
0.0472秒 |
0.0922秒 |
200条 | 0.0310秒 |
0.0584秒 |
0.2319秒 |
500条 | 0.0712秒 |
0.1127秒 |
0.5996秒 |
1000条 | 0.1112秒 |
0.1871秒 |
0.8145秒 |
10000条 | 1.0440秒 |
1.6415秒 |
5.3671秒 |
100000条 | 10.3279秒 |
15.8685秒 |
46.0261秒 |
通过匿名类插入
匿名类的最大优点就是可以不依赖于实体类,不需要为表单独创建一个类,对于需要快速方便快捷的插入数据还是很有用的,插入后如果返回值大于0表示成功,
::: tip
匿句类的字段列名称要与数据库中对应至少要一个字段要对应不然HiSql将会抛出异常
HiSql允许插入的对象列集合大于数据库中的列集合
字段名称忽略大小写
:::
示例HiSql匿名类向表数据写入
int _effect= sqlClient.Insert("HTest01", new { SID =123456, UName ="tansar", Age =25, Salary =1999.9, Descript ="hello world"}).ExecCommand();
如果插入的数据集合大于数据中的列 也可以插入成功,如下所示
//TestColumn 这个列在表HTest01 不存在,如果不存在HiSql底层对数据校验时将会自动忽略它
int _effect= sqlClient.Insert("HTest01", new { SID =123456, UName ="tansar", Age =25, Salary =1999.9, Descript ="hello world",TestColumn="测试"}).ExecCommand();
列的大小写不一致也可以自动识别进行写入
int _effect= sqlClient.Insert("HTest01", new { sid =123456, uname ="tansar", age =25, Salary =1999.9, descript ="hello world" }).ExecCommand();
批量插入匿名类
如果需要向表在插入多条数据请用以下方式
批量写入多少数据没有限制,在HiSql底层是会通过数据大小,列大小自动计算不同的数据库执行数据包大小的最优化方案
List<object> lstdata = new List<object>()
{
new{ sid =123456, UName ="tansar", Age =25, Salary =1999.9, Descript ="hello world"},
new{ sid =123457, UName ="tansar", Age =25, Salary =1999.9, Descript ="hello world"}
};
// 返回大于0表示成功
int _effect4 = sqlClient.Insert("HTest01", lstdata).ExecCommand();
通过字典对象写入
::: tip
字段对象的字段列名称要与数据库中对应至少要一个字段要对应不然HiSql将会抛出异常
HiSql允许插入的对象列集合大于数据库中的列集合
字段名称忽略大小写
当是Dictionary<string, string>
需要加上new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
才可以忽略大小写
:::
//Dictionary<string, object> 对象写入
int _effect = sqlClient.Insert("HTest01",
new Dictionary<string, object> { { "SID", 123456 },{ "UName","tansar" },{ "Age",25 },{ "Salary",1999.9 },{ "descript","hello world" } }
).ExecCommand();
//Dictionary<string, string> 对象写入
int _effect2 = sqlClient.Insert("HTest01",
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase) { { "SID", "123456" }, { "UName", "tansar" }, { "Age", "25" }, { "Salary", "1999.9" }, { "descript", "hello world" } }
).ExecCommand();
如果由前端传入的JSON对象怎样写入?下面就演示一下
通过这个方式就可以将前端传入的JSON数据直接写入到数据表中
string jsondata= "{\"SID\":123456,\"UName\":\"tansar\",\"Age\":25,\"Salary\":1999.9,\"descript\":\"hello world\"}";
var _dicobj = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsondata);
int _effect3 = sqlClient.Insert("HTest01", _dicobj).ExecCommand();
批量字典对象写入
批量通过字典对象数据写入
批量写入多少数据没有限制,在HiSql底层是会通过数据大小,列大小自动计算不同的数据库执行数据包大小的最优化方案
List<Dictionary<string, object>> lstdata = new List<Dictionary<string, object>> {
new Dictionary<string, object> { { "SID", 123456 }, { "UName", "tansar" }, { "Age", 25 }, { "Salary", 1999.9 }, { "descript", "hello world" } },
new Dictionary<string, object> { { "SID", 123457 }, { "UName", "tansar" }, { "Age", 25 }, { "Salary", 1999.9 }, { "descript", "hello world" } }
};
int _effect4 = sqlClient.Insert("HTest01", lstdata).ExecCommand();
通过实体类写入
实体类写入
::: tip
实体类的字段列名称要与数据库中对应至少要一个字段要对应不然HiSql将会抛出异常
HiSql允许插入的对象列集合大于数据库中的列集合
字段名称忽略大小写
:::
int _effect1 = sqlClient.Insert("HTest01", new HTest01 { SID = 123456, UName = "tansar", Age = 25, Salary = 1999, Descript = "hello world" }).ExecCommand();
批量实体数据写入
如以下代码所示
List<HTest01> lstdata = new List<HTest01>()
{
new HTest01 { SID = 123456, UName = "tansar", Age = 25, Salary = 1999, Descript = "hello world" },
new HTest01 { SID = 123457, UName = "tansar", Age = 25, Salary = 1999, Descript = "hello world" }
};
int _effect4 = sqlClient.Insert("HTest01", lstdata).ExecCommand();
多表同时插入
不带事务插入多表
平台我们的业务开发过程中经常一个业务需要同时写入两个表,加上事务控制一个表失败则同时一起滚回,HiSql提供可以同时写两个表的简便操作方法,如下表所示
//同时向表 Hi_Domain 和 Hi_DataElement 插入数据
sqlClient.Insert("Hi_Domain", new { Domain = "TST", DomainDesc = "测试数据类型" })
.Insert("Hi_DataElement", new List<object> {
new { Domain = "TST", ElementValue = "A" } ,
new { Domain = "TST", ElementValue = "B" }
}).ExecCommand();
带事务插入
插入多表张时只要有一张表失败则事务滚回,如下所示
sqlClient.BeginTran();
try
{
sqlClient.Insert("Hi_Domain", new { Domain = "TST", DomainDesc = "测试数据类型" })
.Insert("Hi_DataElement", new List<object> {
new { Domain = "TST", ElementValue = "A" } ,
new { Domain = "TST", ElementValue = "B" }
}).ExecCommand();
sqlClient.CommitTran();
}
catch (Exception E)
{
sqlClient.RollBackTran();
}
插入校验
表检测数据校验
在设计第二范式数据库时经常会把可能重复的数据单独做一种表关联,但是在写入表时为了数据的严谨需要校验一下值在另外一张表中存不存在
如 用一张用户表(HTest01
) 该表表结构如下
其中字段UTYP
的值在另外一张表H_UType
中做了维护表结构如下
为了演示使用我们向H_UType
中写入三条数据如下所示
//在表中添加用户类型 Modi方法的意思是 如果存在则更新没有则插入
sqlClient.Modi("H_UType", new List<object> {
new { UTYP = "U1", UTypeName = "普通用户" },
new { UTYP = "U2", UTypeName = "中级用户" },
new { UTYP = "U3", UTypeName = "高级用户" }
}).ExecCommand();
正常我们向表HTest01
写入数据时字段UTYP
的值必须要存在于表H_UType
中 不然这条数据就是一条不符合逻辑的数据,也可以认为这是条脏数据,在写代码时如果没有做一些校验就有可有把这种数据成功保存到数据库中
HiSql
作者在日常开发过种也经常碰到这种问题,特别是在多业务场景多人团队开发时尤为明显有些开发考虑的全一点就做了校验有些就忽略了,带来系统的Bug的隐患 ,那有没有一种方式可以杜绝这种基本的逻辑错误呢?
Hisql
提供了这个功能,使用过HiSql
的用户肯定知道 在初化始了HiSql
后会产生四张标准表如下所示
Hi_TabModel
Hi_FieldModel
Hi_Domain
Hi_DataElement
但这里不重点把每张表的作用一一介绍,我们需要实现本篇讲的数据检测只需要修改一下配置表Hi_FieldModel
代码如下
sqlClient.Update("Hi_FieldModel", new { TabName = "HTest01", FieldName = "UTYP", IsRefTab=true,RefTab= "H_UType",RefField="UTYP", RefFields = "UTYP,UTypeName",RefFieldDesc= "类型编码,类型名称",RefWhere="UTYP<>''" }).ExecCommand();
执行以上更新代码就是将表HTest01
的字段UTYP
配置了向该表插入数据时 字段UTYP
的值必须要是在表H_UType
中的字段UTYP
中,那么在向表HTest01
写入数据时HiSql
底层将会自动进行校验
可能大家会担心是不是每条数据都会查表校验会不会有性能问题,其实不用担心 HiSql
对这些已经做了特殊处理基本上不用担心如果大家感兴趣可以查看一下HiSql
的源码
那么我们就试一试向表HTest01
插入数据测试一下看
sqlClient.Insert("HTest01", new { SID = "0", UTYP = "U4", UName = "hisql", Age = 36, Salary = 11, Descript = "hisql" }).ExecCommand();
执行以上代码会出现什么情况呢? 是的会抛出异常如下所示
这是HiSql
底层检测完后抛出的异常,以上代码插入的字段UTYP
值U4
不在刚才配置的表H_UType
中,所以这是一种不符合正常业务逻辑的非法数据
修改一下代码
sqlClient.Insert("HTest01", new { SID = "0", UTYP = "U3", UName = "hisql", Age = 36, Salary = 11, Descript = "hisql" }).ExecCommand();
这样就可以正常执行了可以通过HiSql
校验