Unique constraint being violated on the wrong column when using SqlBulkCopy
我正在尝试使用
我的表架构:
1 2 3 4 5 | CREATE TABLE Product ( ID INT IDENTITY (1, 1) PRIMARY KEY, Name NVARCHAR(450) UNIQUE NOT NULL, -- Unique constraint being called BulkInsertID NCHAR(6) -- Column the constraint is being called on ); |
我能想到为什么会发生这种情况的唯一原因是因为我在
最小,完整和可验证的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | class Program { private static SqlConnection connection; private static string connectionURL ="Server=ASUS-X750JA\\DIRECTORY;Database=directory;Integrated Security=True;"; private static Random _random = new Random(); public static SqlConnection openConnection() { connection = new SqlConnection(connectionURL); connection.Open(); Console.WriteLine("Opened connection to DB"); return connection; } public static void closeConnection() { connection.Close(); Console.WriteLine("Closed connection to DB"); } static void Main(string[] args) { List<string> productNames = new List<string>(); productNames.Add("Diamond"); productNames.Add("Gold"); productNames.Add("Silver"); productNames.Add("Platinum"); productNames.Add("Pearl"); addProducts(productNames); } private static void addProducts(List<string> productNames) { const string tableName ="Product"; DataTable table = new DataTable(tableName); string bulkInsertID; do { bulkInsertID = generateID(); } while (isDuplicateBulkInsertID(tableName, bulkInsertID)); DataColumn nameColumn = new DataColumn("Name"); nameColumn.Unique = true; nameColumn.AllowDBNull = false; DataColumn bulkInsertIDColumn = new DataColumn("BulkInsertID"); bulkInsertIDColumn.Unique = false; bulkInsertIDColumn.AllowDBNull = true; table.Columns.Add(nameColumn); table.Columns.Add(bulkInsertIDColumn); foreach (string productName in productNames) { DataRow row = table.NewRow(); row[nameColumn] = productName; row[bulkInsertIDColumn] = bulkInsertID; table.Rows.Add(row); } using (SqlConnection connection = openConnection()) { using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection)) { bulkCopy.DestinationTableName = table.TableName; bulkCopy.WriteToServer(table); } } } /// <summary> /// Generates random 6-character string but it's not like GUID so may need to check for duplicates /// </summary> /// <returns></returns> public static string generateID() { char[] _base62chars ="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".ToCharArray(); int length = 6; var sb = new StringBuilder(length); for (int i = 0; i < length; i++) sb.Append(_base62chars[_random.Next(62)]); return sb.ToString(); } public static bool isDuplicateBulkInsertID(string tableName, string bulkInsertID) { string query = string.Format("SELECT BulkInsertID FROM {0} WHERE BulkInsertID = @bulkinsertid", tableName); SqlCommand command = new SqlCommand(query, openConnection()); SqlParameter bulkInsertIDParam = new SqlParameter("@bulkinsertid", SqlDbType.NChar, bulkInsertID.Length); bulkInsertIDParam.Value = bulkInsertID; command.Parameters.Add(bulkInsertIDParam); command.Prepare(); Task<SqlDataReader> asyncTask = command.ExecuteReaderAsync(); SqlDataReader reader = asyncTask.Result; bool isDuplicate = reader.HasRows; closeConnection(); return isDuplicate; } } |
屏幕截图中显示的唯一约束属于
编辑:我刚刚更改了我的架构,使用
因为您有一个标识列,所以批量插入尝试将
1 2 3 4 5 6 7 | using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection)) { bulkCopy.ColumnMappings.Add("Name","Name"); //NEW bulkCopy.ColumnMappings.Add("BulkInsertID","BulkInsertID"); //NEW bulkCopy.DestinationTableName = table.TableName; bulkCopy.WriteToServer(table); } |
另一个选项是将
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | DataColumn idColumn = new DataColumn("ID"); DataColumn nameColumn = new DataColumn("Name"); //nameColumn.Unique = true; //SqlBulkCopy does not care about these settings. //nameColumn.AllowDBNull = false; DataColumn bulkInsertIDColumn = new DataColumn("BulkInsertID"); //bulkInsertIDColumn.Unique = false; //bulkInsertIDColumn.AllowDBNull = true; table.Columns.Add(ID); table.Columns.Add(nameColumn); table.Columns.Add(bulkInsertIDColumn); foreach (string productName in productNames) { DataRow row = table.NewRow(); //We don't do anything with row[idColumn] row[nameColumn] = productName; row[bulkInsertIDColumn] = bulkInsertID; table.Rows.Add(row); } |
看起来它正在为列
顺便说一句,对我来说看起来它正在抛出异常,因为你试图在循环中创建一个新的
1 2 3 4 | do { bulkInsertID = generateID(); //calling method generateID } while (isDuplicateBulkInsertID(tableName, bulkInsertID)); |
在
1 2 3 4 | public static string generateID() { ........ Random _random = new Random(); // creating new instance every time |