Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#快速上传相关表格_C#_Sql_Sql Server - Fatal编程技术网

C#快速上传相关表格

C#快速上传相关表格,c#,sql,sql-server,C#,Sql,Sql Server,我正在使用动态加载程序。基于定义平面文本文件的数据库表,我可以读取具有多种记录类型的单个文件并将其加载到数据库表中。这些表是相关的,并且使用标识主键。目前一切正常,但运行速度非常慢,因为这一切都是由单insert语句完成的。我正在努力优化流程,但在网上找不到“简单”或“最佳实践”的答案 我当前的项目涉及8个表,但为了简化,我将使用customers/orders示例 让我们看看下面的两个客户,数据文件中的每一组客户和订单都会重复数据。父记录总是在子记录之前。第一个字段是记录类型,每个记录类型对后

我正在使用动态加载程序。基于定义平面文本文件的数据库表,我可以读取具有多种记录类型的单个文件并将其加载到数据库表中。这些表是相关的,并且使用标识主键。目前一切正常,但运行速度非常慢,因为这一切都是由单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语句 添加到数据表
  • 读取数据后,根据数据以正确的顺序批量上载表 关系
  • 解锁表格
  • 结束交易
在我走这条路之前,我想知道是否有人想出了更好的解决方案。我还考虑在SSIS中使用自定义脚本组件。我看到过关于推迟提交交易的帖子和博客,但每个父记录只有几个子记录,树可以有4个深度,考虑订单细节和产品。由于需要父记录ID,我需要提交父记录的插入。我也考虑过自己管理ID而不是身份,但如果可以避免的话,我不想添加额外的管理

根据答案进行更新,以澄清/了解情况

一个典型的文本文件

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列(可选)

为什么您确信需要提交才能从父表获取recordID?几个月前,您的情况与您的情况非常相似,尝试了所有导入方法(Excel/CSV中的RBAR、常规SQL连接等),最后使用了
sqlbulkcopy
。作为过程的一部分,有时需要添加列。为了处理这个问题,我使用新定义创建了一个新表(使用SMO,但并不相关),从旧表中插入行,从新文本文件中插入行,重命名新表,重命名旧表。当然还有其他方法,但这比单独插入要快得多(特别是在定义更改的情况下)。@user6144226我需要保留用于订单插入的客户id。如果我不提交客户插入,我如何确保另一个进程不会执行插入并获取该客户id?@JacobH我的问题是,当我构建数据表时,我需要管理父记录id的保留。如果我需要在相关表上执行多个大容量插入,我看不出该怎么做。因为当您使用标识插入到表中时,该值已被消耗。即使您将其放在事务中并回滚,它也会被消耗。这里的交易似乎只增加了复杂性和可能的性能损失(尽管如此小的交易不太可能)。上下文是每个客户都有几个订单,每个订单都有几个订单细节。每个订单都有一些注释。每个订单都有几笔付款。每次付款都有一对多的票据。现在想象一下50000名顾客。必须提交每个要保留的父键会导致进程运行非常缓慢。对于每个实例要插入的行最多的表,插入行数的平均值是多少?我们说的是100,10000吗?你所描述的数字看起来会从所描述的方法中受益。鉴于你还必须分析一堆CSV数据,我会考虑SSIS,但自从2012以来我就没有用过,所以我不能帮助你。