ADO.net SqlDataAdapter.Update批量插入如何检测主键违规?

时间:2016-04-19 06:15:19

标签: .net tsql ado.net

我正在研究一些使用SqlDataAdapter进行批量插入操作的旧数据访问代码所遇到的问题。目标表有一个主键约束,我需要识别我尝试插入的任何违反此主键的行(即检测重复项)并对这些行采取操作。

大多数情况下,的插入都有重复项,但我确实需要处理这些情况。通过实验,发现执行此批量插入然后查找违规更快,在添加之前单独检查每一行是否存在。

执行此操作的代码如下。

foreach (DataTable dataTable in dataSet.Tables)
  {
    try
    {
      List<string> columns = new List<string>();
      foreach (DataColumn column in dataTable.Columns)
        columns.Add(column.ColumnName);

      string commandText = "select " + String.Join(",", columns.ToArray()) + " from " + dataTable.TableName;

      SqlCommand sqlCommand = new SqlCommand(commandText, conn);
      SqlDataAdapter dataAdapter = new SqlDataAdapter(sqlCommand);
      dataAdapter.ContinueUpdateOnError = true;
      SqlCommandBuilder sqlBuilder = new SqlCommandBuilder(dataAdapter);
      dataAdapter.Update(dataTable);

    }
    catch (Exception)
    {
      // No exception should be thrown with ContinueUpdateOnError = true
    }
  }

  return dataSet;

注意dataAdapter.ContinueUpdateOnError = true;表示任何错误都不会抛出任何异常(永远不会输入异常块)

因此,一旦运行上述内容,我们可以使用以下代码查找任何错误,包括任何主要密钥违规行为......

foreach (DataTable dataTable in dataSet)
{
    foreach (DataRow dataRow in dataTable.Rows)
    { 
        if (dataRow.HasErrors)
        {
           // Here I want to detect if the error was a primary key violation, or something else
        }
    }
}

所以,我可以通过上面的.HasErrors检测到某种错误的行,但我看不出一种好的方法来检测这个错误是主键违规。那里的一个RowError属性,但这只是文字... Violation of PRIMARY KEY constraint 'PK_MYKEY'. Cannot insert duplicate key in object 'dbo.MY_TABLE'. The duplicate key value is (6215). The statement has been terminated.

我能看到区别于其他错误(例如磁盘错误等)的唯一方法是搜索上面的一些文本,但这似乎不是很强大或良好的做法(错误文本可能会改变,或者如果运行不同的语言/文化,文本也会不同)

dataRow还有一个ErrorState属性(似乎总是说Added,并且还有一个错误对象,但它只有相同的文本,没有真正的额外信息。

有没有办法让我获得有关实际错误的更好信息,例如:如果是主键违规,或者在上述方案中是否存在?

提前致谢!

1 个答案:

答案 0 :(得分:0)

一种选择是将数据批量插入空的临时表,然后运行将临时表中的数据合并到实际表中的存储过程。如果不是问题,您还可以调整查询以排除重复项。

我还建议您使用SqlBulkCopy进行批量操作。根据我的经验,SqlBulkCopy是将.NET中的数据批量加载到SQL Server的最快方法。您还可以设置许多有用的属性。

https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy(v=vs.110).aspx