当表中存在依赖关系时,如何进行SqlBulkCopy?

Jac*_*per 1 c# sqlbulkcopy

当不依赖于表时,我可以使用以下代码执行 SqlBulkCopy:

//TableData and FieldData have column info in memory.  
using (SqlConnection connection = new SqlConnection(@"Data Source=WLO1;Initial Catalog=GenTest2;Integrated Security=True"))
        {

            connection.Open();
            foreach (string tableName in tablesInOrderToProcess)
            {
                if (tableDataList.ContainsKey(tableName))
                {
                    TableData td = tableDataList[tableName];

                    SqlBulkCopy copy = new SqlBulkCopy(connection);
                    copy.BatchSize = 10000;
                    copy.DestinationTableName = tableName;

                    System.Data.DataTable dt = new DataTable();
                    foreach (FieldData fd in td.FieldList.Values)
                    {
                        string fieldName = fd.Name;
                        string fieldDataType = fd.DataType;
                        string fieldSize = fd.Size.ToString(); ;
                        string fieldConstant = fd.constantValue;
                        string fieldAverage = fd.averageSize;
                        string fieldPickList = fd.pickList;
                        copy.ColumnMappings.Add(fieldName, fieldName);
                        switch (fieldDataType)
                        {
                            case "char":
                                {
                                    dt.Columns.Add(fieldName, System.Type.GetType("System.String"));
                                }
                                break;
                            case "nvarchar":
                                {
                                    dt.Columns.Add(fieldName, System.Type.GetType("System.String"));
                                }
                                break;
                            case "number":
                                {
                                    if (fd.Size == 10)
                                        dt.Columns.Add(fieldName, System.Type.GetType("System.Int64"));
                                    else
                                        dt.Columns.Add(fieldName, System.Type.GetType("System.Int32"));
                                }
                                break;
                            default:
                                {
                                    dt.Columns.Add(fieldName);
                                }
                                break;
                        }
                    }
                    for (int i = 0; i < int.Parse(td.NumRows); i++)
                    {
                        System.Data.DataRow r = dt.NewRow();
                        foreach (FieldData fd in td.FieldList.Values)
                        {
                            string fieldName = fd.Name;
                            string fieldDataType = fd.DataType;
                            string fieldSize = fd.Size.ToString(); ;
                            string fieldConstant = fd.constantValue;
                            string fieldAverage = fd.averageSize;
                            string fieldPickList = fd.pickList;

                            switch (fieldDataType)
                            {
                                case "char":
                                    {
                                        if (fd.averageSize.Length > 0)
                                        {
                                            r[fieldName] = GetRandomString(Int32.Parse(fd.averageSize), true);
                                        }
                                        else
                                        {
                                            r[fieldName] = fieldConstant;
                                        }
                                    }
                                    break;
                                case "nvarchar":
                                    {
                                        if (fd.averageSize.Length > 0)
                                        {
                                            r[fieldName] = GetRandomString(Int32.Parse(fd.averageSize), true);
                                        }
                                        else
                                        {
                                            r[fieldName] = fieldConstant;
                                        }
                                    }
                                    break;
                                case "number":
                                    {
                                        if (fd.Size == 10)
                                        {
                                            r[fieldName] = i;
                                        }
                                        else
                                        {
                                            r[fieldName] = i;
                                        }
                                    }
                                    break;
                                default:
                                    {
                                        r[fieldName] = fieldConstant;
                                    }
                                    break;
                            }

                        }
                        dt.Rows.Add(r);
                    }

                    try
                    {
                        copy.WriteToServer(dt);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                }
            }
        }
Run Code Online (Sandbox Code Playgroud)

然而,当存在依赖性时,我会感到困惑。 依赖性

1)我应该为每个表创建一个DataTable吗?

2)由于表关系信息是由用户提供并加载到内存中的,如何在不从模式中读取信息的情况下绑定表?或者我是否必须读取信息并从架构中获取主键?

提前致谢。我希望我说清楚了。

Sco*_*ain 5

在这种情况下,唯一的方法是对临时表执行批量复制操作,而没有链接两个对象的键(以及足够的元数据来稍后构建链接)。

假设您有 3 个表:#item_unit_staging#shop_order_staging#shop_order_operation_stagingitem_unit您可以使用与、 、相同的架构shop_ordershop_order_operation使用自动生成的主键来创建它们。您还需要添加用于链接本地计算机内存中的数据的任何数据作为“元数据列”,假设我们使用了一个名为 onmetadata_id所有三个表的额外列和一个名为parent_idon#shop_order_staging和 的列#shop_order_operation_staging

然后,我们批量插入到我们的 3 个表中,填充主键列并留下外键列NULL。一旦我们在服务器上有了数据,我们就可以使用元数据列来填充外键列。

update #shop_order_staging 
    set parent_item_unit_id = #item_unit_staging.item_unit_id
    from #shop_order_staging
    inner join #item_unit_staging on #shop_order_staging.parent_id = #item_unit_staging.metadata_id

update #shop_order_operation_staging 
    set parent_shop_order_id = #shop_order_staging.shop_order_id
    from #shop_order_operation_staging
    inner join #shop_order_staging on #shop_order_operation_staging.parent_id = #shop_order_staging.metadata_id
Run Code Online (Sandbox Code Playgroud)

然后,您可以将数据从临时表复制到真实表中

insert into item_unit 
    select item_unit_id
         , /*all other columns except [metadata_id]*/ 
    from #item_unit_staging


insert into shop_order 
    select shop_order_id
         , parent_item_unit_id
         , /*all other columns except metadata_id and parent_id*/ 
    from #shop_order_staging

insert into shop_order_operation 
    select shop_order_operation_id
         , parent_shop_order_id
         , /*all other columns except metadata_id and parent_id*/ 
    from #shop_order_operation_staging
Run Code Online (Sandbox Code Playgroud)