【问题标题】:SqlBulkCopy Violates Unique Constraint with Wrong ValueSqlBulkCopy 违反具有错误值的唯一约束
【发布时间】:2018-11-21 06:04:17
【问题描述】:

我有一个看起来像这样的表:

CREATE TABLE [dbo].[Site]
(
    [Id] INT NOT NULL IDENTITY(1, 1) PRIMARY KEY, 
    [Name] NVARCHAR(MAX) NOT NULL, 
    [CreatedAt] DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    [UpdatedAt] DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    [DeletedAt] DATETIME NULL, 
    CONSTRAINT [AK_Site_Name] UNIQUE ([Name])
)

我正在从文件中加载数据,对其进行解析和操作,然后将其上传回来。这发生在如下所示的数据表中:

Name | CreatedAt | UpdatedAt

我在读取文件后循环创建它,如下所示:

DataTable dt = new DataTable() { TableName = "Site" };

var dc = new DataColumn("Name", typeof(string)) { Unique = True };
dt.Columns.Add(dc);

dc = new DataColumn("CreatedAt", typeof(DateTime));
dt.Columns.Add(dc);

dc = new DataColumn("UpdatedAt", typeof(DateTime));
dt.Columns.Add(dc);

foreach(var rec in myFile) {
    var dr = dt.NewRow();
    dr[0] = rec.SiteName;
    dr[1] = DateTime.UtcNow;
    dr[2] = DateTime.UtcNow;
    dt.Rows.Add(dr);
}

最后像这样将它传递给 SqlBulkCopy:

var connection = new SqlConnection(ConnectionString);

        var bulkCopy =
            new SqlBulkCopy
                (connection,
                    SqlBulkCopyOptions.TableLock |
                    SqlBulkCopyOptions.FireTriggers |
                    SqlBulkCopyOptions.UseInternalTransaction,
                    null
                )
            {
                DestinationTableName = "Site",
                BatchSize = 1000
            };
        connection.Open();
        bulkCopy.WriteToServer(dataTable);
        connection.Close();

我得到一个例外:

违反 UNIQUE KEY 约束“AK_Site_Name”。无法在对象“dbo.Site”中插入重复键。重复键值为 (11/21/2018 5:52:13 AM)。

在调试器中检查我的数据表显示列是正确的。数据表本身没有错误。

我试图在 SSMS 中复制如下:

DECLARE @currentd DATETIME = CURRENT_TIMESTAMP;

INSERT INTO [dbo].[Site] (Name, CreatedAt, UpdatedAt) VALUES ('Test', @currentd, @currentd), ('Test', @currentd, @currentd)

当然,正如预期的那样,它运行良好。这让我相信以某种方式为Name 字段输入了一个日期,但我不确定如何。

有没有人经历过这种情况并可以指出正确的方向?

【问题讨论】:

  • 您的站点名称重复
  • @JohnB 这怎么可能?我在数据表上设置了唯一性,违规值是日期时间?
  • 好的,在调试器中仔细检查 dr 变量中的列是否符合您的预期 - 例如 dr[0] 是真的站点名称等。
  • @JohnB @Disaffected1070452 我正在使用CsvHelper。我已经验证了数据表中的每一行都是正确的数据类型

标签: c# sql-server datatable sqlbulkcopy


【解决方案1】:

dr[0] 用于应设置为 null 的列 ID,因此最终循环应如下所示:

foreach(var rec in myFile) {
 var dr = dt.NewRow();
 dr[0] = null;
 dr[1] = rec.SiteName;
 dr[2] = DateTime.UtcNow;
 dr[3] = DateTime.UtcNow;
 dt.Rows.Add(dr); }

【讨论】:

  • yip...这就是我在评论中所暗示的
  • 这不正确 - The string was not recognized as a valid DateTime. There is an unknown word starting at index 0.Couldn't store <ABCDE> in CreatedAt Column. Expected type is DateTime.
  • @CL40 你定义了列吗? var dc = new DataColumn("Id", typeof(INT)); dt.Columns.Add(dc);
  • @ElyasEsna Cannot set Column 'Id' to be null. Please use DBNull instead.
猜你喜欢
  • 2016-07-27
  • 2016-10-24
  • 2020-02-15
  • 1970-01-01
  • 2011-10-17
  • 2012-03-03
  • 2018-08-26
  • 2021-10-23
  • 1970-01-01
相关资源
最近更新 更多