SqlBulkCopy 插入 table with Identity
SqlBulkCopy inserting in a table with Identity
这是我的场景:
我必须在 table 中导入大文件,所以我使用了 sqlBulkCopy,因为其他方法太慢了。
这是文件行的示例:
String1|String2|String3|String4
这是 table 结构:
Id (Identity,PK)|Column1|Column2|Column3|Column4
我用'|'分割行,我创建数据表,我把table的每一列(除了Id)通过配置文件读取信息:
DataColumn dc;
foreach (Tables.BulkColumn bc in columns)
{
dc = new DataColumn();
dc.DataType = bc.ColumnValueType;
dc.ColumnName = bc.Name;
dc.Unique = false;
actualDataTable.Columns.Add(dc);
}
我将数据从文件加载到数据表(这里的数据是正确的),初始化 SqlBulkCopy 和 writeToServer:
SqlBulkCopy sbc = new SqlBulkCopy(connectionString, SqlBulkCopyOptions.TableLock);
sbc.BulkCopyTimeout = 600;
sbc.WriteToServer(actualDataTable);
但是,当我查看数据库时,这是插入的行:
IncrementedId|String2|String3|String4
它不插入 Column1 值,它似乎与列索引一起使用,但初始化 dataColumns 我明确设置了名称。
你知道怎么解决吗?必须自动插入 Id 并正确写入其他值。
(我尝试将 Id 移动到最后一列,这样可以正常工作,但我不喜欢这种解决方案)
更新
为了将数据从 txt 插入到 table,我从我的配置中读取了 table 结构,例如
<table name="Table" file="D:\Progetti\TestArea\test\SqlBulkCopy\FP20150716003004.txt" incremental="false" active="true" identity="true">
<field name="Column1" type="System.String" default="" key="false" allowsNull="true" length="50" />
<!-- Other Fields --> ...
所有字段的顺序与输入文件中列的顺序相同。
我拆分文件行并将数据放入 DataRow:
dr[actualIndexColumnName] = string.IsNullOrEmpty(splitted[columnIndex]) ? tab.Columns[columnIndex].DefaultValue : splitted[columnIndex];
其中 splitted[columnIndex] 是实际输入值,当该行的所有列都被填充时,我将其添加到 DataTable
dt.Rows.Add(dr);
您的 SqlBulkCopy
缺少一个 column map。
foreach (Tables.BulkColumn bc in columns)
{
sbc.ColumnMapping.Add(bc.name);
}
我通过以这种方式将映射添加到 SqlBulkCopy 解决了我的问题:
sbc.ColumnMappings.Clear();
int i = hasTableIdentity ? 1 : 0;
DataColumn dc;
foreach (Tables.BulkColumn bc in columns)
{
dc = new DataColumn();
dc.DataType = bc.ColumnValueType;
dc.ColumnName = bc.Name;
dc.Unique = false;
sbc.ColumnMappings.Add(dc.ColumnName, i);
actualDataTable.Columns.Add(dc);
i++;
}
这是我的场景: 我必须在 table 中导入大文件,所以我使用了 sqlBulkCopy,因为其他方法太慢了。
这是文件行的示例:
String1|String2|String3|String4
这是 table 结构:
Id (Identity,PK)|Column1|Column2|Column3|Column4
我用'|'分割行,我创建数据表,我把table的每一列(除了Id)通过配置文件读取信息:
DataColumn dc;
foreach (Tables.BulkColumn bc in columns)
{
dc = new DataColumn();
dc.DataType = bc.ColumnValueType;
dc.ColumnName = bc.Name;
dc.Unique = false;
actualDataTable.Columns.Add(dc);
}
我将数据从文件加载到数据表(这里的数据是正确的),初始化 SqlBulkCopy 和 writeToServer:
SqlBulkCopy sbc = new SqlBulkCopy(connectionString, SqlBulkCopyOptions.TableLock);
sbc.BulkCopyTimeout = 600;
sbc.WriteToServer(actualDataTable);
但是,当我查看数据库时,这是插入的行:
IncrementedId|String2|String3|String4
它不插入 Column1 值,它似乎与列索引一起使用,但初始化 dataColumns 我明确设置了名称。
你知道怎么解决吗?必须自动插入 Id 并正确写入其他值。
(我尝试将 Id 移动到最后一列,这样可以正常工作,但我不喜欢这种解决方案)
更新
为了将数据从 txt 插入到 table,我从我的配置中读取了 table 结构,例如
<table name="Table" file="D:\Progetti\TestArea\test\SqlBulkCopy\FP20150716003004.txt" incremental="false" active="true" identity="true">
<field name="Column1" type="System.String" default="" key="false" allowsNull="true" length="50" />
<!-- Other Fields --> ...
所有字段的顺序与输入文件中列的顺序相同。 我拆分文件行并将数据放入 DataRow:
dr[actualIndexColumnName] = string.IsNullOrEmpty(splitted[columnIndex]) ? tab.Columns[columnIndex].DefaultValue : splitted[columnIndex];
其中 splitted[columnIndex] 是实际输入值,当该行的所有列都被填充时,我将其添加到 DataTable
dt.Rows.Add(dr);
您的 SqlBulkCopy
缺少一个 column map。
foreach (Tables.BulkColumn bc in columns)
{
sbc.ColumnMapping.Add(bc.name);
}
我通过以这种方式将映射添加到 SqlBulkCopy 解决了我的问题:
sbc.ColumnMappings.Clear();
int i = hasTableIdentity ? 1 : 0;
DataColumn dc;
foreach (Tables.BulkColumn bc in columns)
{
dc = new DataColumn();
dc.DataType = bc.ColumnValueType;
dc.ColumnName = bc.Name;
dc.Unique = false;
sbc.ColumnMappings.Add(dc.ColumnName, i);
actualDataTable.Columns.Add(dc);
i++;
}