# DBHub
**Repository Path**: clementine/dbhub
## Basic Information
- **Project Name**: DBHub
- **Description**: sqlserver数据库实现数据批量插入、修改和删除的组件
- **Primary Language**: C#
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 2
- **Created**: 2020-12-28
- **Last Updated**: 2024-04-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: 产品
## README
# DBHub
### 特别提醒
**数据无价,Bug无情,请先找测试数据确认学会正确用法,以免发生删库跑路等意外。**
### 一、概述
#### 1.1 背景
刚工作的时候,作为萌新,干的最多的就是增删改查,那个时候叫CRUD Boy,天天拼接什么insert,update,写得很烦躁,特别是后来遇到很多复杂的操作场景,比如某个表需要同时进行N个操作:插入X行、同时更新Y行、同时删除Z行,这么多事情需要拼接多少sql语句啊,那个时候NET的ORM也不好用,而且批处理能力弱,于是萌生了一个想法:能否写一个方法一次性完成全部处理动作,于是DBHub就这样诞生了。
#### 1.2 介绍
DBHub是一个sqlserver数据库增删改查批处理工具。DBHub的作用是为了方便地将数据集(以下简称dt)批量写入数据表,使用者只需要把数据集按照要求组装起来,作为参数传递给DBHub的方法,剩下的事情由DBHub全部搞定。
DBHub可以
1. 将所有对数据表的增删改操作通过对dt的控制一次性更新到数据表;
1. 对dt与数据表重叠的数据可以采用略过或者更新的方式自由控制;
1. 判断送入的dt与数据表结构是否一致,提示缺少的字段或者多出的字段;
1. 判断主键是否一致;
#### 1.3 开源
这是我为开源世界贡献的第一个组件,该组件已经应用到我的工程物料管理系统中。
#### 1.4 使用范围
目前只支持MSSQL。
#### 1.5 效果演示
[https://live.csdn.net/v/139749](https://live.csdn.net/v/139749)
#### 1.6 补充介绍文章
[《DBHub的前世今生》](https://blog.csdn.net/xiangcns/article/details/112002113)
### 二、安装教程
开发项目直接引用类文件即可
### 三、成员方法
#### 方法1:
```
///
/// 数据导入
///
/// 连接对象
/// 数据集
/// 架构名
/// 表名
/// 关键字名数组(判断数据项的唯一性用)
/// 对重复数据的处理方式
/// 长度为2的字符数组<执行代码,提示>
public string[] DataImport(SqlConnection conn, DataTable dt, string schemaName, string tableName, string sqlfilter, string[] KeyColumnName, DuplicateProcessMode dupType)
```
|参数名称 | 参数类型 | 说明 |
|---|---|---|
|conn| SqlConnection| 连接对象|
|dt| DataTable| 数据集|
|schemaName| string| 架构名|
|tableName| string| 表名|
|sqlfilter| string| 表的查询条件,这个查询条件的作用是从数据表中查询一个参照系ds,然后用dt与ds做比对,这样的好处是缩小了参照系的尺寸,提高了dt写入数据表的错误(试想如果数据表有百万行数据,而你此时dt打算写入10行数据,却要对一百万行进行遍历检查是否重复,这样的操作命中率太低)|
|KeyColumnName| string[]| 主键数组(因为有的表主键可能不止一个字段)|
|dupType| DuplicateProcessMode| 对重叠数据的处理方式:Update 更新重复数据,Ignore 忽略重复数据|
#### 方法2
```
///
/// 数据更新
///
///
///
///
///
///
///
/// 已经存在项处理方式
/// 长度为2的字符数组<执行代码,提示>
public string[] DataUpdate(SqlConnection conn, DataTable dt, string schemaName, string tableName, string sqlfilter, string[] KeyColumnName, DuplicateProcessMode dupMode)
```
|参数名称 | 参数类型 | 说明 |
|---|---|---|
|conn| SqlConnection| 连接对象|
|dt| DataTable| 数据集|
|schemaName| string| 架构名|
|tableName| string| 表名|
|sqlfilter| string| 表的查询条件,这个查询条件的作用是从数据表中查询一个参照系ds,然后用dt与ds做比对,这样的好处是缩小了参照系的尺寸,提高了dt写入数据表的错误(试想如果数据表有百万行数据,而你此时dt打算写入10行数据,却要对一百万行进行遍历检查是否重复,这样的操作命中率太低)。特别注意在使用DataUpdate方法时,dt没有的数据会从参照系中删除,如果你想批量删除数据,切记要用sqlfilter参数查询出参照系,而不是以整个数据表作为参照系,否则数据表会只剩下dt的数据。|
|KeyColumnName| string[]| 主键数组(因为有的表主键可能不止一个字段)|
|dupType| DuplicateProcessMode| 对重叠数据的处理方式:Update 更新重复数据,Ignore 忽略重复数据|
**严重警告:**
特别注意在使用DataUpdate方法时,dt没有的数据会从参照系中删除,如果你想批量删除数据,切记要用sqlfilter参数查询出参照系,而不是以整个数据表作为参照系,否则数据表会只剩下dt的数据。如果你没有搞懂这段话的意思,切记不可使用DataUpdate方法。
#### 方法3
```
///
/// 数据导入
///
///
///
///
///
///
///
///
/// 已经存在项处理方式
/// 长度为2的字符数组<执行代码,提示>
public string[] DataImport(SqlConnection conn, SqlTransaction sqltrans, DataTable dt, string schemaName, string tableName, string sqlfilter, string[] KeyColumnName, DuplicateProcessMode dupType)
```
|参数名称 | 参数类型 | 说明 |
|---|---|---|
|conn| SqlConnection| 连接对象|
|sqltrans| SqlTransaction| 事务对象|
|dt| DataTable| 数据集|
|schemaName| string| 架构名|
|tableName| string| 表名|
|sqlfilter| string| 表的查询条件,这个查询条件的作用是从数据表中查询一个参照系ds,然后用dt与ds做比对,这样的好处是缩小了参照系的尺寸,提高了dt写入数据表的错误(试想如果数据表有百万行数据,而你此时dt打算写入10行数据,却要对一百万行进行遍历检查是否重复,这样的操作命中率太低)|
|KeyColumnName| string[]| 主键数组(因为有的表主键可能不止一个字段)|
|dupType| DuplicateProcessMode| 对重叠数据的处理方式:Update 更新重复数据,Ignore 忽略重复数据|
#### 方法4
```
///
/// 数据更新
///
///
///
///
///
///
///
///
/// 已经存在项处理方式
/// 长度为2的字符数组<执行代码,提示>
public string[] DataUpdate(SqlConnection conn, SqlTransaction sqltrans, DataTable dt, string schemaName, string tableName, string sqlfilter, string[] KeyColumnName, DuplicateProcessMode dupMode)
```
|参数名称 | 参数类型 | 说明 |
|---|---|---|
|conn| SqlConnection| 连接对象|
|sqltrans| SqlTransaction| 事务对象|
|dt| DataTable| 数据集|
|schemaName| string| 架构名|
|tableName| string| 表名|
|sqlfilter| string| 表的查询条件,这个查询条件的作用是从数据表中查询一个参照系ds,然后用dt与ds做比对,这样的好处是缩小了参照系的尺寸,提高了dt写入数据表的错误(试想如果数据表有百万行数据,而你此时dt打算写入10行数据,却要对一百万行进行遍历检查是否重复,这样的操作命中率太低)。特别注意在使用DataUpdate方法时,dt没有的数据会从参照系中删除,如果你想批量删除数据,切记要用sqlfilter参数查询出参照系,而不是以整个数据表作为参照系,否则数据表会只剩下dt的数据。|
|KeyColumnName| string[]| 主键数组(因为有的表主键可能不止一个字段)|
|dupType| DuplicateProcessMode| 对重叠数据的处理方式:Update 更新重复数据,Ignore 忽略重复数据|
严重警告:
同方法2
### 四、使用方法
#### 4.1 dt的构造方法
```
//构造dt的方式1
DataTable dt= new DataTable(); //询价单材料量表写入格式
bulkDataTable.Columns.AddRange(new DataColumn[]{
new DataColumn("PJGUID",typeof(System.Guid)),
new DataColumn("PSGUID",typeof(System.Guid)),
new DataColumn("KSGUID",typeof(System.Guid)),
new DataColumn("采购包编号",typeof(System.String)),
new DataColumn("修改者",typeof(string)),
new DataColumn("修改时间",typeof(DateTime))});
```
```
//构造dt的方式2
DataTable dt = new DataTable();
dt.Columns.Add("PLGUID");
dt.Columns.Add("LOCKey");
dt.Columns.Add("项目ID");
dt.Columns.Add("PSGUID");
dt.Columns.Add("XDGUID");
dt.Columns.Add("箱单号");
dt.Columns.Add("放行单");
```
#### 4.2、不带事务的用法
```
//数据库连接对象(用于dbpc.GetConnectionString()获取连接字符串)
DatabaseMaterialControl dbpc = new DatabaseMaterialControl();
//声明conn对象
SqlConnection conn = new SqlConnection(dbpc.GetConnectionString());
//声明DBHub对象
DBHub.DBHub imp = new DBHub.DBHub();
string[] keyColumnName = { "LOCKey" }; //数据表的主键
string[] answerStr = new string[2]; //返回值(返回值是一个数组)
//调用DataImport,将dt写入表:合同箱单信息表
answerStr = imp.DataImport(conn, dt, "Material", "合同箱单信息表", "WHERE 项目ID='" + ProjectID.ToString() + "'", keyColumnName, DBHub.DuplicateProcessMode.Update);
```
#### 4.3、带事务的用法
```
项目数据库连接类 dbpc = new 项目数据库连接类();
SqlConnection conn = new SqlConnection(dbpc.GetConnectionString());
using (conn)
{
//事务开始
if (conn.State != ConnectionState.Open)
{
conn.Open(); //打开连接
}
SqlTransaction sqltrans = conn.BeginTransaction(); //事务对象
try
{
DBHub.DBHub impSummary = new DBHub.DBHub();
string[] keyColumnNameSummary = { "ISGUID", "领料单号" };
string[] answerStrSummary = new string[2];
string messageBULKSummary = string.Empty;
answerStrSummary = impSummary.DataImport(conn, sqltrans, dtSummary, "Material", "出库概要信息表", "WHERE 项目ID='" + ProjectID + "'", keyColumnNameSummary, DBHub.DuplicateProcessMode.Ignore);
DBHub.DBHub impDetails = new DBHub.DBHub();
string[] keyColumnNameDetails = { "LOCKey" };
string[] answerStrDetails = new string[2];
string messageBULKDetails = string.Empty;
answerStrDetails = impDetails.DataImport(conn, sqltrans, dtDetails, "Material", "出库明细信息表", "WHERE 项目ID='" + ProjectID + "'", keyColumnNameDetails, DBHub.DuplicateProcessMode.Update);
if (answerStrSummary[0] == "[1]" && answerStrDetails[0] == "[1]")
{
iRel = "Done";
messageBULK = "success";
}
else if (answerStrSummary[0] != "[1]")
{
iRel = "L7001";
messageBULK = "出库单概要信息写入错误:" + answerStrSummary[0] + answerStrSummary[1];
}
else if (answerStrDetails[0] != "[1]")
{
iRel = "L7002";
messageBULK = "出库单明细信息写入错误:" + answerStrDetails[0] + answerStrDetails[1];
}
sqltrans.Commit();
}
catch (Exception e)
{
iRel = "L7003";
sqltrans.Rollback();
messageBULK = e.Message;
}
finally
{
if (conn.State != ConnectionState.Closed)
{
conn.Close(); //关闭连接
}
}
}
```
### 五、错误代码
```
*【错误代码】
* 0 参数dt没有数据(0行)
* 1 执行成功
* 31 KeyColumnName参数中的主键列名在数据库目标表中不存在
* 32 参数dt表结构与数据库表结构不一致,dt缺少字段[value]
* 33 参数dt表结构与数据库表结构不一致,dt多出字段[value]
* 90 来自vs debug 的try/cacth报错
* 98 KeyColumnNameIsNotExistIndb或者dtColumnNameIsNotMatchTodb变量值异常
* 99 不存在的错误代码,看到这个错误代码等于见到鬼
```