当没有依赖于表时,我可以使用以下代码执行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);
}
}
}
}
1)我应该为每个表创建一个DataTable吗?
2)由于表关系信息由用户提供并加载到内存中,如何在不读取模式信息的情况下绑定表?或者我是否必须阅读信息并从Schema获取主键?
提前致谢。我希望我说清楚。
答案 0 :(得分:4)
在这种情况下,唯一可行的方法是将批量复制操作执行到临时表,而没有键链接这两个对象(以及稍后构建链接的足够元数据)。
假设您有3个表:#item_unit_staging
,#shop_order_staging
和#shop_order_operation_staging
。您可以使用与item_unit
,shop_order
和shop_order_operation
相同的架构使用自动生成的主键创建它们。您还希望添加用于链接本地计算机内存中数据的任何数据作为&#34;元数据列&#34;,假设我们在所有三个表上使用了一个名为metadata_id
的额外列, parent_id
和#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
然后,您可以将临时表中的数据复制到真实表
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