【问题标题】:Using SQLBulkCopy to Insert into Related Tables使用 SQLBulkCopy 插入相关表
【发布时间】:2017-07-04 06:08:34
【问题描述】:

我正在使用 SQL 批量复制将数据从 Excel 读取到 SQL DB。在数据库中,我有两个表,我需要从 Excel 中插入这些数据。 Table ATable B 使用来自 Table A 的 ID(主键 IDENTITY)将相应的行记录插入到 Table B
我可以使用以下代码插入一个表 (Table A)。

using (SqlConnection connection = new SqlConnection(strConnection)) {
    connection.Open();
    using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection)) {
        bulkCopy.DestinationTableName = "dbo.[EMPLOYEEINFO]";
        try {
            // Write from the source to the destination.
            SqlBulkCopyColumnMapping NameMap = new SqlBulkCopyColumnMapping(data.Columns[0].ColumnName, "EmployeeName");
            SqlBulkCopyColumnMapping GMap = new SqlBulkCopyColumnMapping(data.Columns[1].ColumnName, "Gender");
            SqlBulkCopyColumnMapping CMap = new SqlBulkCopyColumnMapping(data.Columns[2].ColumnName, "City");
            SqlBulkCopyColumnMapping AMap = new SqlBulkCopyColumnMapping(data.Columns[3].ColumnName, "HomeAddress");

            bulkCopy.ColumnMappings.Add(NameMap);
            bulkCopy.ColumnMappings.Add(GMap);
            bulkCopy.ColumnMappings.Add(CMap);
            bulkCopy.ColumnMappings.Add(AMap);

            bulkCopy.WriteToServer(data);
        }
        catch (Exception ex) {
            Console.WriteLine(ex.Message);
        }
    }
}

但是我不知道如何为两个受外键关系绑定的表扩展它。特别是,Table B 使用来自Table A 的标识值任何示例都会很棒。我用谷歌搜索了它,SO 上的所有线程都无法给出一个工作示例。

【问题讨论】:

  • 这个方法只能加载一张表。为什么不使用两个数据表及其关系集创建一个 DataSet,然后保存该数据集?
  • @rene 我认为 DataSet 路由不起作用有两个原因。首先,关键是一个身份,因此在创建 DataSet 时不知道值,其次我认为您不能批量复制 DataSet,只是一个 DataTable,我认为 OP 对速度感兴趣!
  • @JonathanWillcock 当然,在那种情况下我并不是要使用 SqlBulkCopy 。如果速度是问题,那么我宁愿先测试,如果它真的很重要。
  • 先插入临时表,然后使用 SQL 查询管理对基表的插入。这将使处理IDENTITY 值变得更加容易,因为您可以使用INSERTOUTPUT 子句来捕获它们。
  • @Alex,基本表中已经有一些行。你的技术在这种情况下也有效吗?请指点我一些完整的资源来看看你的想法。谢谢

标签: c# sql-server database excel


【解决方案1】:

AFAIK 批量复制只能用于上传到单个表中。为了实现将批量上传到两个表中,您将需要两次批量上传。您的问题来自使用作为身份的外键。但是,您可以解决此问题。我很确定批量复制是按顺序上传的,这意味着如果您上传 1,000 条记录,最后一条记录的 ID 为 10,197,那么第一条记录的 ID 为 9,198!所以我的建议是上传你的第一个表,上传后检查最大 id,减去记录数,然后从那里开始工作!

当然,在高使用率的数据库中,有人可能会在您之后插入,因此您需要通过选择与您的最后一条记录匹配的其他详细信息来获取顶部 id(假设(最多)所有字段的组合将是保证是唯一的)。只有您知道这是否可能是一个问题。

替代方法是首先不使用标识列,但我认为您无法控制设计?在我年轻的时候,我犯了使用身份的错误,我现在从来没有这样做过。他们总能找到办法回来咬人!

例如添加第二条数据:

DataTable secondTable = new DataTable("SecondTable");
secondTable.Columns.Add("ForeignKey", typeof(int));
secondTable.Columns.Add("DataField", typeof(yourDataType));

...

将数据添加到 secondTable。

(取决于第二个数据的格式)

int cnt = 0;
foreach (var d in mySecondData)
{
    DataRow newRow = secondTable.NewRow();
    newRow["ForeignKey"] = cnt;
    newRow["DataField"] = d.YourData;
    secondTable.Rows.Add(newRow);
}

然后在你找到起始身份(int startID)之后。

for (int i = 0; i < secondTable.Rows.Count; i++)
{
    secondTable["ForeignKey"] = secondTable["ForeignKey"] + startID;
}

最后:

bulkCopy.DestinationTableName = "YourSecondTable";
bulkCopy.WriteToServer(secondTable);

【讨论】:

  • 我可以保证在我们执行此操作期间没有人插入数据库。是的,我也无法控制数据库设计。基本上这是一个请求系统的后端数据库。现在用户想要插入大约 1000 个批量请求,而无需从 ui 提交它们。
  • 那么,你能举个例子来说明这个多表插入是如何工作的吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-17
  • 2014-11-26
  • 2010-11-04
  • 1970-01-01
  • 2014-09-10
  • 2011-06-23
  • 1970-01-01
相关资源
最近更新 更多