C# SqlBulkCopy插入到具有标识的表中
这是我的设想: 我必须导入表中的大型文件,所以我使用sqlBulkCopy,因为其他方法太慢 这是文件行的一个示例:C# SqlBulkCopy插入到具有标识的表中,c#,sql,datatable,sqlbulkcopy,C#,Sql,Datatable,Sqlbulkcopy,这是我的设想: 我必须导入表中的大型文件,所以我使用sqlBulkCopy,因为其他方法太慢 这是文件行的一个示例: String1|String2|String3|String4 这是表格结构: Id (Identity,PK)|Column1|Column2|Column3|Column4 我按“|”拆分行,创建dataTable,将表的每一列(除了Id)放入其中,通过配置文件读取信息: DataColumn dc; foreach (Tables.BulkColumn bc in co
String1|String2|String3|String4
这是表格结构:
Id (Identity,PK)|Column1|Column2|Column3|Column4
我按“|”拆分行,创建dataTable,将表的每一列(除了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);
}
我将数据从文件加载到dataTable(此处的数据正确),初始化SqlBulkCopy和writeToServer:
SqlBulkCopy sbc = new SqlBulkCopy(connectionString, SqlBulkCopyOptions.TableLock);
sbc.BulkCopyTimeout = 600;
sbc.WriteToServer(actualDataTable);
但是,当我查看数据库时,这是插入的行:
IncrementedId|String2|String3|String4
它不插入Column1值,它似乎与columns索引一起工作,但初始化dataColumns时我显式地设置了名称
你知道怎么解决吗?必须自动插入Id并正确写入其他值
(我尝试将Id移动为最后一列,这样可以正常工作,但我不喜欢此解决方案)
更新
为了将数据从txt插入表中,我从配置中读取表结构,例如
<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 --> ...
其中splitted[columnIndex]是实际的输入值,当该行的所有列都已填充时,我将此列添加到DataTable中
dt.Rows.Add(dr);
您的SqlBulkCopy
缺少一个
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++;
}
可能的副本。这个问题本质上是关于
SqlBulkCopy
如何处理标识列的。(设置SqlBulkCopyOptions.KeepIdentity=true,也许吧?@stakx我尝试设置SqlBulkCopyOptions.KeepIdentity=true,但它给了我一个System.FormatException,因为它似乎可以使用索引(Id是int,column1是nvarchar)也许你应该停下来想想为什么column1
是nvarchar
。它不应该是int
,就像在实际的数据库模式中一样吗?如果是这样,这是否意味着您可能需要修改构建数据表的代码(即在字符串.Split
之后添加类似int.Parse
)?我编辑了插入表中的问题更改值,以澄清除Id之外的列是nvarchar1。如果显示将输入转换为DataTable
的代码,将会有所帮助。2.Re:“当我在数据库中查找时,这是插入的行”-SELECT语句是什么样子的?您的解决方案可以工作,但不存在只接受一个参数的Add重载,因此我使用了接受columnName、columnPosition的重载。
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++;
}