C#快速上传相关表格
我正在使用动态加载程序。基于定义平面文本文件的数据库表,我可以读取具有多种记录类型的单个文件并将其加载到数据库表中。这些表是相关的,并且使用标识主键。目前一切正常,但运行速度非常慢,因为这一切都是由单insert语句完成的。我正在努力优化流程,但在网上找不到“简单”或“最佳实践”的答案 我当前的项目涉及8个表,但为了简化,我将使用customers/orders示例 让我们看看下面的两个客户,数据文件中的每一组客户和订单都会重复数据。父记录总是在子记录之前。第一个字段是记录类型,每个记录类型对后面的字段有不同的定义。这些都在控制表中指定C#快速上传相关表格,c#,sql,sql-server,C#,Sql,Sql Server,我正在使用动态加载程序。基于定义平面文本文件的数据库表,我可以读取具有多种记录类型的单个文件并将其加载到数据库表中。这些表是相关的,并且使用标识主键。目前一切正常,但运行速度非常慢,因为这一切都是由单insert语句完成的。我正在努力优化流程,但在网上找不到“简单”或“最佳实践”的答案 我当前的项目涉及8个表,但为了简化,我将使用customers/orders示例 让我们看看下面的两个客户,数据文件中的每一组客户和订单都会重复数据。父记录总是在子记录之前。第一个字段是记录类型,每个记录类型对后
CUST|Joe Green|123 Main St
ORD|Pancakes|5
ORD|Nails|2
CUST|John Deere|456 Park Pl
ORD|Tires|4
现行守则将:
- 插入customer Joe Green并返回ID(使用输出 insert语句中的Inserted.Id)
- 插入订单、煎饼和钉子,并附上返回的ID
- 插入客户John Deere并返回一个ID
- 插入带有退货ID的订单轮胎
- 创建事务
- 在本例中,锁定属于“文件定义”一部分的所有表 客户和订单获得每个表的最大ID,并增加一个 为所有表设置起始ID
- 为所有表创建datatable
- 按当前设置执行,但不发出insert语句 添加到数据表
- 读取数据后,根据数据以正确的顺序批量上载表 关系
- 解锁表格
- 结束交易
one file header record
- 5 facility records that relate to the file header
- 7,000 customers(account)
- 5 - 10 notes per customer
- 1-5 payments at the account level
- 1-5 adjustments at the account level
- 5 - 20 orders per customer
- 5 - 20 order details per order
- 1-5 payments at the order level
- 1-5 adjustments at the order level
- one file trailer record related to the file header
Keys
- File Header -> Facility -> Customer (Account)
- File Header -> FileTrailer
- Customer -> Notes
- Customer -> Payments
- Customer -> Adjustments
- Customer -> Orders
- Order -> OrderDetails
- Order -> Payments
- Order -> Adjustments
这里还涉及到一些表格,但这应该可以让您了解整个上下文
Data Sample ... = MORE FIELDS .... MORE RECORDS
HEADER|F1|F2|...
FACILITY|F1|F2|..
CUSTOMER|F1|F2|...
NOTE|F1|F2|....
....
ORDER|F1|F2|...
ORDERDETAIL|F1|F2|...
.... ORDER DETAILS
ORDERPYMT|F1|F2|...
....
ORDERADJ|F1|F2|...
....
CUSTOMERPYMT|F1|F2|...
....
CUSTOMERADJ|F1|F2|...
....
(The structure repeats for each facility)
TRAILER|F1|F2|...
插入数据量较低的相关表通常不会有问题。如果他们进展缓慢,我们需要更多的背景来回答你的问题 如果由于要插入的记录太多而遇到问题,则可能需要查看。
如果您不想自己管理id,我所知道的最干净的方法就是使用临时占位符id列
- 使用数据和临时ID列创建并填充数据表,您自己填充,外键为空
- SqlBulkCopy主表
- 通过tempids列从先前插入的表中查找主键,使用生成的外键更新辅助datatable
- 上载辅助表
- 重复,直到完成
- 删除临时id列(可选)
sqlbulkcopy
。作为过程的一部分,有时需要添加列。为了处理这个问题,我使用新定义创建了一个新表(使用SMO,但并不相关),从旧表中插入行,从新文本文件中插入行,重命名新表,重命名旧表。当然还有其他方法,但这比单独插入要快得多(特别是在定义更改的情况下)。@user6144226我需要保留用于订单插入的客户id。如果我不提交客户插入,我如何确保另一个进程不会执行插入并获取该客户id?@JacobH我的问题是,当我构建数据表时,我需要管理父记录id的保留。如果我需要在相关表上执行多个大容量插入,我看不出该怎么做。因为当您使用标识插入到表中时,该值已被消耗。即使您将其放在事务中并回滚,它也会被消耗。这里的交易似乎只增加了复杂性和可能的性能损失(尽管如此小的交易不太可能)。上下文是每个客户都有几个订单,每个订单都有几个订单细节。每个订单都有一些注释。每个订单都有几笔付款。每次付款都有一对多的票据。现在想象一下50000名顾客。必须提交每个要保留的父键会导致进程运行非常缓慢。对于每个实例要插入的行最多的表,插入行数的平均值是多少?我们说的是100,10000吗?你所描述的数字看起来会从所描述的方法中受益。鉴于你还必须分析一堆CSV数据,我会考虑SSIS,但自从2012以来我就没有用过,所以我不能帮助你。