[英]SqlBulkCopy and DataTables with Parent/Child Relation on Identity Column
[英]SqlBulkCopy Insert with Identity Column
我正在使用SqlBulkCopy
object 将几百万生成的行插入到数据库中。 唯一的问题是我要插入的表有一个标识列。 我尝试将SqlBulkCopyOptions
设置为SqlBulkCopyOptions.KeepIdentity
并将标识列设置为0
的DbNull.Value
和null
。 这些都没有用。 我觉得我错过了一些非常简单的东西,如果有人能启发我,那就太好了。 谢谢!
编辑澄清一下,我没有在我导入的DataTable
中设置标识值。 我希望它们作为导入的一部分生成。
编辑 2这是我用来创建基础SqlBulkCopy
object 的代码。
SqlBulkCopy sbc = GetBulkCopy(SqlBulkCopyOptions.KeepIdentity);
sbc.DestinationTableName = LOOKUP_TABLE;
private static SqlBulkCopy GetBulkCopy(SqlBulkCopyOptions options =
SqlBulkCopyOptions.Default)
{
Configuration cfg = WebConfigurationManager.OpenWebConfiguration("/RSWifi");
string connString =
cfg.ConnectionStrings.ConnectionStrings["WifiData"].ConnectionString;
return new SqlBulkCopy(connString, options);
}
要让目标表分配标识,请不要使用SqlBulkCopyOptions.KeepIdentity
选项。 相反,不要 map 来自源的身份,也不要从源中提取它以发送到SqlBulkCopy
。
填写ColumnMapping
object 的BulkCopy
并且不要 map 标识列。 标识列将由目标数据库生成。
是的,你是对的,使用SqlBulkCopyOptions.KeepIdentity
选项然后批量复制编写器不认为你是什么表结构这个 object 从开始列写入,所以为了我们的需要,我正在以同样的方式在我的表中保留身份字段只是你必须在数据表 object 中创建一个额外的列,其中 rest 是您需要的列,并将 null 值传递给该列,然后表会自动处理身份。
这就是我在 .NET Core 中解决它的方法( dt
是您的数据表):
dt.Columns.Cast<DataColumn>().ForEach((c, i) => sqlBulkCopy.ColumnMappings.Add(c.ColumnName, i + 1));
您基本上通过为目标列分配从 1 而不是 0 开始的序数来跳过身份 ( Id
) 列。
这是桌子
CREATE TABLE [dbo].[ProductShippingMethodMap](
[Id] [int] IDENTITY(1,1) NOT NULL,
[ProductId] [int] NOT NULL,
[ShippingMethodId] [int] NOT NULL,
[ParentProductId] [int] NOT NULL,
CONSTRAINT [PK_ProductShippingMethodMap] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
下面的 C# 代码正在工作
DataTable dtQtyData = new DataTable();
dtQtyData.Clear();
dtQtyData.Columns.Add("Id", typeof(int));
dtQtyData.Columns.Add("ProductId", typeof(int));
dtQtyData.Columns.Add("ShippingMethodId", typeof(int));
dtQtyData.Columns.Add("ParentProductId", typeof(int));
for (int i = 0; i < ShippingMethodIds.Length; i++)
{
for (int j = 0; j < ProductIds.Length; j++)
{
var productId = ProductIds[j];
var shippingMethodId = ShippingMethodIds[i];
dtQtyData.Rows.Add(new object[] {0,productId, shippingMethodId, parentProductId });
}
}
var connectionString = new DataSettingsManager().LoadSettings().DataConnectionString;
SqlBulkCopy bulkcopy = new SqlBulkCopy(connectionString, SqlBulkCopyOptions.Default);
bulkcopy.DestinationTableName = "ProductShippingMethodMap";
bulkcopy.WriteToServer(dtQtyData);
你有两个选择——
1 - 使用KeepIdentity
并保留源的Identity
值。
2 - 不要 map Identity
字段。 如果您不尝试分配值,目标表将自动分配一个值。
使用 JDBC SQLServerBulkCSVFileRecord 结构时,确实需要映射标识列,但忽略标识列中的值。
原因:- 数据末尾的 excel 中有一些空行,可能看起来像空白行。 批量上传试图将这些空白行上传到表中。
解决方案:- Select 仅包含数据的行 - 将数据复制到新工作表中。 假设您在“表 1”中有数据,将其移动到“表 2”并删除“表 1”。
在我的情况下,它原来是列名内的空格,并且在我的 SQL 表中意外使用连字符 (-) 而不是下划线 (_) 的列之一中。 我在 sql 表中用下划线替换了空格和连字符,它解决了问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.