Exécution d'une instruction de fusion via C # SqlCommand ne fonctionne pas

Je tente d'abord d'utiliser une table temporaire et une instruction MERGE pour mettre à jour une table SQL via un object SqlCommand en C #. Le programme sur lequel je travaille est conçu pour exporter d'abord un très grand nombre d'loggings (plus de 20k +) dans une feuille de calcul Excel. L'user a alors la possibilité de faire une search et de replace pour une valeur spécifique et de mettre à jour autant de champs dans autant d'loggings qu'ils le souhaitent.

Ce que j'essaie de faire est alors prendre cette feuille de calcul, remplir un DataTable avec elle, puis remplir une table SQL temporaire avec le DataTable utilisant SqlBulkCopy .

J'utilise ensuite une instruction MERGE pour mettre à jour les lignes si elles existent encore dans la database.

Cependant, le problème que j'ai est une contrainte unique que j'ai sur la table ZipCodeTerritory continue à être déclenchée en me donnant le message d'erreur suivant:

Impossible d'insert une ligne de key en double dans l'object 'dbo.ZipCodeTerritory' avec l'index unique 'UQ_ChannelStateEndDateZipCodeISNULL'. La valeur de la key en double est (9, CA, 94351, 9999-12-31).

Cela m'amène à croire que, d'une manière ou d'une autre, l'instruction UPDATE n'est pas en cours d'exécution ou que j'ai joint les tables de manière incorrecte dans la partie de l'instruction en utilisant le mot key ON . La contrainte unique est uniquement déclenchée pendant les instructions INSERT ou UPDATE dans les StateCode ChannelCode , StateCode , StateCode ou EndDate . Je fais une mise à jour de masse sur le champ IndDistrnId et j'ai soigneusement vérifié la feuille de calcul.

Encore une fois, c'est ma première tentative d'essayer cette technique, donc toute aide / suggestion serait grandement appréciée. Merci

C #

 private static ssortingng updateCommand = "UPDATE SET Target.ChannelCode = Source.ChannelCode, Target.DrmTerrDesc = Source.DrmTerrDesc, Target.IndDistrnId = Source.IndDistrnId," + "Target.StateCode = Source.StateCode, Target.ZipCode = Source.ZipCode, Target.EndDate = Source.EndDate, Target.EffectiveDate = Source.EffectiveDate," + "Target.LastUpdateId = Source.LastUpdateId, Target.LastUpdateDate = Source.LastUpdateDate, Target.ErrorCodes = Source.ErrorCodes," + "Target.Status = Source.Status "; //Load updates into datatable DataTable table = LoadData(updates); //Script to create temp table ssortingng tmpTable = "CREATE TABLE [dbo].[ZipCodeTerritoryTemp]( " + "[ChannelCode] [char](1) NOT NULL, " + "[DrmTerrDesc] [nvarchar](30) NOT NULL, " + "[IndDistrnId] [char](3) NULL, " + "[StateCode] [char](3) NOT NULL, " + "[ZipCode] [char](9) NULL, " + "[EndDate] [date] NOT NULL, " + "[EffectiveDate] [date] NOT NULL, " + "[LastUpdateId] [char](8) NULL, " + "[LastUpdateDate] [date] NULL, " + "[Id] [int] IDENTITY(1,1) NOT NULL, " + "[ErrorCodes] [varchar](255) NULL, " + "[Status] [char](1) NULL, " + "CONSTRAINT [PK_ZipCodeTerritoryTemp] PRIMARY KEY NONCLUSTERED " + "( " + "[Id] ASC " + ")WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY] " + ") ON [PRIMARY]"; using (SqlConnection connection = new SqlConnection(connSsortingng)) { connection.Open(); //Create temp table SqlCommand cmd = new SqlCommand(tmpTable, connection); cmd.ExecuteNonQuery(); try { using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection)) { //Write to temp table bulkCopy.DestinationTableName = "ZipCodeTerritoryTemp"; bulkCopy.WriteToServer(table); //Merge changes in temp table with ZipCodeTerritory ssortingng mergeSql = "merge ZipCodeTerritory as Target " + "using ZipCodeTerritoryTemp as Source " + "on " + "Target.Id = Source.Id " + "when matched then " + updateCommand + ";"; cmd.CommandText = mergeSql; int results = cmd.ExecuteNonQuery(); //Drop temp table cmd.CommandText = "DROP TABLE [dbo].[ZipCodeTerritoryTemp]"; cmd.ExecuteNonQuery(); } } catch (Exception) { throw; } finally { //Drop temp table SqlCommand final = new SqlCommand("DROP TABLE [dbo].[ZipCodeTerritoryTemp]", connection); final.ExecuteNonQuery(); } } 

SQL

Pour des raisons de lisibilité, voici l'instruction MERGE telle que je l'ai écrite dans SQL Server Management Studio. J'ai copié ceci dans le C #. FYI – a couru cette déclaration dans Management Studio et a reçu exactement le même message d'erreur.

 MERGE INTO ZipCodeTerritory as Target USING ZipCodeTerritoryTemp as Source ON Target.Id = Source.Id WHEN MATCHED THEN UPDATE SET Target.ChannelCode = Source.ChannelCode, Target.DrmTerrDesc = Source.DrmTerrDesc, Target.IndDistrnId = Source.IndDistrnId, Target.StateCode = Source.StateCode, Target.ZipCode = Source.ZipCode, Target.EndDate = Source.EndDate, Target.EffectiveDate = Source.EffectiveDate, Target.LastUpdateId = Source.LastUpdateId, Target.LastUpdateDate = Source.LastUpdateDate, Target.ErrorCodes = Source.ErrorCodes, Target.Status = Source.Status; 

Le problème a fini par être la propriété IDENTITY définie dans le champ Id de la table temporaire. Après avoir enlevé cela, j'ai pu lancer le MERGE sans erreur. Voici la table temporaire maintenant:

 //Script to create temp table ssortingng tmpTable = "CREATE TABLE [dbo].[ZipCodeTerritoryTemp]( " + "[ChannelCode] [char](1) NOT NULL, " + "[DrmTerrDesc] [nvarchar](30) NOT NULL, " + "[IndDistrnId] [char](3) NULL, " + "[StateCode] [char](3) NOT NULL, " + "[ZipCode] [char](9) NULL, " + "[EndDate] [date] NOT NULL, " + "[EffectiveDate] [date] NOT NULL, " + "[LastUpdateId] [char](8) NULL, " + "[LastUpdateDate] [date] NULL, " + "[Id] [int] NOT NULL, " + //DO NOT GIVE THE PK OF THE TEMP TABLE AN IDENTITY(1,1,) PROPRETY "[ErrorCodes] [varchar](255) NULL, " + "[Status] [char](1) NULL, " + "CONSTRAINT [PK_ZipCodeTerritoryTemp] PRIMARY KEY NONCLUSTERED " + "( " + "[Id] ASC " + ")WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY] " + ") ON [PRIMARY]";