SqlBulkCopy插入标识列

时间:2011-07-11 14:38:05

标签: c# sql-server sqlbulkcopy identity-insert

我正在使用SqlBulkCopy对象将数百万个生成的行插入数据库。唯一的问题是我插入的表有一个标识列。我尝试将SqlBulkCopyOptions设置为SqlBulkCopyOptions.KeepIdentity并将标识列设置为0DbNull.Valuenull。其中没有一个有效。我觉得我错过了一些非常简单的事情,如果有人能够启发我会很棒。谢谢!

编辑为了澄清,我没有在我导入的DataTable中设置的身份值。我希望它们作为导入的一部分生成。

编辑2     这是我用来创建基础SqlBulkCopy对象的代码。

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);
}

8 个答案:

答案 0 :(得分:34)

要让目标表分配标识,请不要使用SqlBulkCopyOptions.KeepIdentity选项。相反,不要映射来自源的身份,也不要从源中提取它以发送到SqlBulkCopy

答案 1 :(得分:21)

填写BulkCopy对象的ColumnMapping,不要映射标识列。标识列将由目标数据库生成。

答案 2 :(得分:1)

您有两种选择 -

1 - 使用KeepIdentity并保留来源的Identity值。

2 - 不映射Identity字段。如果您不尝试分配值,目标表将自动分配一个值。

答案 3 :(得分:1)

是的,你是正确的使用SqlBulkCopyOptions.KeepIdentity选项然后批量复制编写器不认为你的表结构是什么,这个对象从开始列写,所以为了我们的需要,我以同样的方式保留身份字段在我的表中,你只需要在你的数据表对象中创建一个额外的列,其余的你需要的列并将空值传递给该列,然后表自动处理Identity。

答案 4 :(得分:1)

这是桌子

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);

答案 5 :(得分:0)

这就是我在.NET Core中解决它的方式(dt是您的数据表):

dt.Columns.Cast<DataColumn>().ForEach((c, i) => sqlBulkCopy.ColumnMappings.Add(c.ColumnName, i + 1));

通过为目标列分配从1开始而不是0的序数,基本上可以跳过标识(Id)列。

答案 6 :(得分:-1)

原因: - 数据末尾的Excel中有一些空行,可能看起来像空行。批量上传试图将这些空白行上传到表格中。

解决方案: - 仅选择包含数据的行 - 将数据复制到新工作表中。假设您在'Sheet 1'中有数据,将其移至'Sheet 2'并删除'Sheet 1'。

答案 7 :(得分:-1)

在我的情况下,结果是列名称中的空白区域和我在SQL表中意外使用hyphon( - )而不是下划线(_)的列之一。 我在sql表中用下划线替换了空格和hyphon,它修复了问题。