【问题标题】:SqlBulkCopy Insert with Identity Column带有标识列的 SqlBulkCopy 插入
【发布时间】:2011-10-02 20:50:34
【问题描述】:

我正在使用SqlBulkCopy 对象将生成的几百万行插入到数据库中。唯一的问题是我要插入的表有一个标识列。我尝试将SqlBulkCopyOptions 设置为SqlBulkCopyOptions.KeepIdentity,并将标识列设置为0's、DbNull.Valuenull。这些都没有奏效。我觉得我错过了一些非常简单的东西,如果有人能启发我,那就太棒了。谢谢!

edit 澄清一下,我没有在我正在导入的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);
}

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

    • 我实际上需要在插入时生成标识值,如果有帮助的话。
    • 哦,你要给目的地赋值吗?你的问题根本不清楚。不要使用SqlBulkCopyOptions.KeepIdentity!关闭它,不要将其包含在映射中,也不要在您从 source 拉取时包含它。
    • 哦,我被文档 When not specified, identity values are assigned by the destination. 弄糊涂了,我以为这意味着没有指定值:(
    • @FlyingStreudel:没错。 SqlBulkCopyOptions 中有很多选项。当您不指定SqlBulkCopyOptions.KeepIdentity 选项时,目标表将分配标识。
    【解决方案2】:

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

    【讨论】:

    • 这刚刚解决了一个困扰我几个小时的问题。
    • 这很有帮助,因为我的源/目标有不同的列数。源数据具有用于以特定格式显示数据的列。这也意味着数据库中有重复的数据。所以我使用 ColumnMappings 集合跳过了源数据中不需要保存在数据库中的某些列。
    • 虽然我认为这是我的问题的答案,但我并没有真正理解这个答案。如果您不将标识列添加到DataTable,例如returnVal.Columns.Add("Id", typeof(int)); 然后你会遇到映射问题。不过,不应为此列分配值,因此不要添加dataRow["id"] = ...etc.
    【解决方案3】:

    你有两个选择-

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

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

    【讨论】:

    • 不赋值变量等同于赋值DbNull.Value。我仍然得到相同的Column 'Id' does not allow DBNull.Value. IOE :( 或者你的意思是在我的DataTable 中甚至不包括Id 列?
    • @Flying - 你是否关闭了KeepIdentity?目标必须是FALSE 才能赋值。
    • 我添加了用于创建SqlBulkCopy 对象的代码。我没有看到要设置的名为 KeepIdentity 的字段/属性。
    • @Flying - 抱歉,不要设置为 TRUE。如果已设置,目的地将不会自动分配身份
    【解决方案4】:

    这是桌子

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

    【讨论】:

    • 我不断收到主键重复违规。
    • 不应该像表定义的[Id] [int] IDENTITY(1,1) NOT NULL,是主键,自增1。所以应该遵守规则。
    【解决方案5】:

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

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

    您基本上跳过身份 (Id) 列,方法是为您的目标列分配从 1 而不是 0 开始的序数。

    【讨论】:

      【解决方案6】:

      是的,你是对的,使用 SqlBulkCopyOptions.KeepIdentity 选项然后批量复制作者不认为你是什么表结构这个对象从开始列写入,所以为了我们的需要,我正在以同样的方式在我的表只是你必须在你的数据表对象中创建一个额外的列和你需要的列并将空值传递给这个列然后表会自动处理标识。

      【讨论】:

        【解决方案7】:

        在我的情况下,它原来是列名内的空格,并且在我的 SQL 表中不小心使用连字符 (-) 而不是下划线 (_) 的列中。 我在 sql 表中用下划线替换了空格和连字符,它解决了问题。

        【讨论】:

          【解决方案8】:

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

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

          【讨论】:

            猜你喜欢
            • 2015-10-10
            • 1970-01-01
            • 1970-01-01
            • 2011-08-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-02-17
            • 1970-01-01
            相关资源
            最近更新 更多