none
Violation PK en bulkCopy

    Question

  • Bonjour,

    J'ai développé une procédure CLR afin d'insérer des données en masse vers une table SQL Server

     [Microsoft.SqlServer.Server.SqlProcedure]
           public static void IntegrationFactureSage(string dsn,string server, string db)//(DateTime d1, DateTime d2, SqlString t1, SqlString t2)
            {
              
                string reqSQL = "";
                #region **** Récupération des données à partir de sage ****
                OdbcConnection conn = new OdbcConnection("DSN=" + dsn);
                reqSQL = "select DO_DATE,DO_PIECE,DO_TIERS,FNT_NETAPAYER,DO_TYPE,DO_DOMAINE,DO_COURS,do_devise from f_docentete where  DO_Type IN(4,5,6,7)";
                    //" and DO_DATE>= CAST('" + d1.ToShortDateString() + "' AS DATETIME) and DO_DATE<= CAST('" + d2.ToShortDateString() + "' AS DATETIME)";
                    //" and  DO_TIERS between '" + t1.ToString() + "' and '" + t2.ToString() + "'";
                OdbcCommand myCommand = new OdbcCommand(reqSQL, conn);
                conn.Open();
                DataSet myDataSet = new DataSet();
                OdbcDataAdapter myAdapter = new OdbcDataAdapter(reqSQL, conn);
                myAdapter.Fill(myDataSet, "AR_SELECFACTURE");
                DataColumn[] columns = new DataColumn[2];
                columns[0]=myDataSet.Tables["AR_SELECFACTURE"].Columns["DO_PIECE"];
                columns[1]=myDataSet.Tables["AR_SELECFACTURE"].Columns["DO_TYPE"];
                myDataSet.Tables["AR_SELECFACTURE"].PrimaryKey = columns;
                conn.Close();
                
                #endregion
    
                #region **** insertion dans la base de règlement ****
                try
                {
                        SqlConnection cn = new SqlConnection(@"Data Source="+server+";Initial Catalog="+db+";Integrated Security=True");
                    cn.Open();
                    SqlBulkCopy bulkcopy = new SqlBulkCopy(cn, SqlBulkCopyOptions.KeepIdentity,null);
                    bulkcopy.ColumnMappings.Add("DO_PIECE", "DO_PIECE");
                    bulkcopy.ColumnMappings.Add("DO_TYPE", "DO_TYPE");
                    bulkcopy.DestinationTableName = myDataSet.Tables["AR_SELECFACTURE"].TableName;
                    bulkcopy.WriteToServer(myDataSet.Tables["AR_SELECFACTURE"]);
    
                    cn.Close();
                }
                catch (Exception ee)
                {
                    SqlContext.Pipe.Send(ee.Message);
                    SqlContext.Pipe.Send(ee.Data.ToString());
                    SqlContext.Pipe.Send(ee.InnerException.ToString());
                    SqlContext.Pipe.Send(ee.TargetSite.ToString());
                }
                
                #endregion
            }


    Comme vous remarquez j'ai définit la clé primaire de la table source 

    DataColumn[] columns = new DataColumn[2];
                columns[0]=myDataSet.Tables["AR_SELECFACTURE"].Columns["DO_PIECE"];
                columns[1]=myDataSet.Tables["AR_SELECFACTURE"].Columns["DO_TYPE"];
                myDataSet.Tables["AR_SELECFACTURE"].PrimaryKey = columns;

    et pour inserer les données j'ai utilisé  

    SqlBulkCopy bulkcopy = new SqlBulkCopy(cn, SqlBulkCopyOptions.KeepIdentity,null);

    mais je reçois toujours l'erreur suivante

    Violation de la contrainte PRIMARY KEY 'PK_AR_SELECFACTURE'. Impossible d'insérer une clé en double dans l'objet 'dbo.AR_SELECFACTURE'.
    L'instruction a été arrêtée.
    System.Collections.ListDictionaryInternal
    Msg 6522, Niveau 16, État 1, Procédure IntegrationFactureSage, Ligne 0
    Une erreur .NET Framework s'est produite au cours de l'exécution de la routine ou de la fonction d'agrégation définie par l'utilisateur "IntegrationFactureSage" : 
    System.NullReferenceException: La référence d'objet n'est pas définie à une instance d'un objet.
    System.NullReferenceException: 
       à DSN_CLR.ImportSageFact.IntegrationFactureSage(String dsn, String server, String db)

    Merci

    lundi 2 septembre 2013 08:38

Réponses

Toutes les réponses

  • Bonjour,

    J'ai développé une procédure CLR afin d'insérer des données en masse vers une table SQL Server

     [Microsoft.SqlServer.Server.SqlProcedure]
           public static void IntegrationFactureSage(string dsn,string server, string db)//(DateTime d1, DateTime d2, SqlString t1, SqlString t2)
            {
              
                string reqSQL = "";
                #region **** Récupération des données à partir de sage ****
                OdbcConnection conn = new OdbcConnection("DSN=" + dsn);
                reqSQL = "select DO_DATE,DO_PIECE,DO_TIERS,FNT_NETAPAYER,DO_TYPE,DO_DOMAINE,DO_COURS,do_devise from f_docentete where  DO_Type IN(4,5,6,7)";
                    //" and DO_DATE>= CAST('" + d1.ToShortDateString() + "' AS DATETIME) and DO_DATE<= CAST('" + d2.ToShortDateString() + "' AS DATETIME)";
                    //" and  DO_TIERS between '" + t1.ToString() + "' and '" + t2.ToString() + "'";
                OdbcCommand myCommand = new OdbcCommand(reqSQL, conn);
                conn.Open();
                DataSet myDataSet = new DataSet();
                OdbcDataAdapter myAdapter = new OdbcDataAdapter(reqSQL, conn);
                myAdapter.Fill(myDataSet, "AR_SELECFACTURE");
                DataColumn[] columns = new DataColumn[2];
                columns[0]=myDataSet.Tables["AR_SELECFACTURE"].Columns["DO_PIECE"];
                columns[1]=myDataSet.Tables["AR_SELECFACTURE"].Columns["DO_TYPE"];
                myDataSet.Tables["AR_SELECFACTURE"].PrimaryKey = columns;
                conn.Close();
                
                #endregion
    
                #region **** insertion dans la base de règlement ****
                try
                {
                        SqlConnection cn = new SqlConnection(@"Data Source="+server+";Initial Catalog="+db+";Integrated Security=True");
                    cn.Open();
                    SqlBulkCopy bulkcopy = new SqlBulkCopy(cn, SqlBulkCopyOptions.KeepIdentity,null);
                    bulkcopy.ColumnMappings.Add("DO_PIECE", "DO_PIECE");
                    bulkcopy.ColumnMappings.Add("DO_TYPE", "DO_TYPE");
                    bulkcopy.DestinationTableName = myDataSet.Tables["AR_SELECFACTURE"].TableName;
                    bulkcopy.WriteToServer(myDataSet.Tables["AR_SELECFACTURE"]);
    
                    cn.Close();
                }
                catch (Exception ee)
                {
                    SqlContext.Pipe.Send(ee.Message);
                    SqlContext.Pipe.Send(ee.Data.ToString());
                    SqlContext.Pipe.Send(ee.InnerException.ToString());
                    SqlContext.Pipe.Send(ee.TargetSite.ToString());
                }
                
                #endregion
            }

    Comme vous remarquez j'ai définit la clé primaire de la table source 

    DataColumn[] columns = new DataColumn[2];
                columns[0]=myDataSet.Tables["AR_SELECFACTURE"].Columns["DO_PIECE"];
                columns[1]=myDataSet.Tables["AR_SELECFACTURE"].Columns["DO_TYPE"];
                myDataSet.Tables["AR_SELECFACTURE"].PrimaryKey = columns;

    et pour inserer les données j'ai utilisé  

    SqlBulkCopy bulkcopy = new SqlBulkCopy(cn, SqlBulkCopyOptions.KeepIdentity,null);

    mais je reçois toujours l'erreur suivante

    Violation de la contrainte PRIMARY KEY 'PK_AR_SELECFACTURE'. Impossible d'insérer une clé en double dans l'objet 'dbo.AR_SELECFACTURE'.
    L'instruction a été arrêtée.
    System.Collections.ListDictionaryInternal
    Msg 6522, Niveau 16, État 1, Procédure IntegrationFactureSage, Ligne 0
    Une erreur .NET Framework s'est produite au cours de l'exécution de la routine ou de la fonction d'agrégation définie par l'utilisateur "IntegrationFactureSage" : 
    System.NullReferenceException: La référence d'objet n'est pas définie à une instance d'un objet.
    System.NullReferenceException: 
       à DSN_CLR.ImportSageFact.IntegrationFactureSage(String dsn, String server, String db)

    Merci

    lundi 2 septembre 2013 09:26
  • Bonjour

    Une clef primaire ajoute aussi une contrainte d'unicité.

    Le plus probable, dans votre source de données, cette condition n’est pas respectée.

    Pouvez-vous faire un teste sans spécifier la clef primaire ?

    Cordialement,


    Aurel BERA, MSFT
    MSDN Community Support. LE CONTENU EST FOURNI "TEL QUEL" SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE.
    S'il vous plaît n'oubliez pas de "Marquer comme réponse" les réponses qui ont résolu votre problème. C'est une voie commune pour reconnaître ceux qui vous ont aidé, et rend plus facile pour les autres visiteurs de trouver plus tard la résolution.

    lundi 2 septembre 2013 13:07
    Propriétaire
  • Bonjou,

    Oui effectivement c'est ce que j'ai fait, j'ai fais le test sans PK et ça marche très bien aussi j'ai vérifié les valeurs dans ma base s'il existe des doublons ou non

    select DO_PIECE, DO_TYPE from F_DOCENTETE
    group by DO_PIECE,DO_TYPE
    having count(*)>1

    cordialement

    lundi 2 septembre 2013 16:13
  • Bonjour,

    Cela montre qu'il n'y a pas de doublons *dans les données source*. Mais si un couple (DO_PIECE,DO_TYPE) est déjà présent dans la table de destination, vous aurez tout de même une violation de pk.

    Si j'ai bien compris cela a marché après suppression de la PK sur AR_FACTURE (?) mais c'est maintenant peut-être dans la table de destination AR_FACTURE qu'il faudrait vérifier la présence de doublons ?


    Please always mark whatever response solved your issue so that the thread is properly marked as "Answered".

    lundi 2 septembre 2013 22:55
    Modérateur
  • Bonjour,

    Exactement Patrice, peut être j'ai mal exprimé mon besoin dès le debut.

    Ce que je voulais faire c'est d'insérer les données de façon incrémentale c'est a dire l'équivalence de :

    Insert into table_dest (col1, col2)select (val1, val2) from table_sourcewhere val1 not in (select val1 from table_dest);
    Cordialement.

    mardi 3 septembre 2013 07:47
  • Dans ce cas je vous suggère de utiliser une table temporaire (ou intermédiaire) ou charger les informations continues par le fichier.

    Après ca, vous faites un

    INSERT INTO table_dest

    select * from table_interm where....

    Cordialement,


    Aurel BERA, MSFT
    MSDN Community Support. LE CONTENU EST FOURNI "TEL QUEL" SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE.
    S'il vous plaît n'oubliez pas de "Marquer comme réponse" les réponses qui ont résolu votre problème. C'est une voie commune pour reconnaître ceux qui vous ont aidé, et rend plus facile pour les autres visiteurs de trouver plus tard la résolution.

    mardi 3 septembre 2013 09:42
    Propriétaire
  • Bonjour

    Un petit retour SVP?

    Merci.

    Cordialement,


    Aurel BERA, MSFT
    MSDN Community Support. LE CONTENU EST FOURNI "TEL QUEL" SANS GARANTIE D'AUCUNE SORTE, EXPLICITE OU IMPLICITE.
    S'il vous plaît n'oubliez pas de "Marquer comme réponse" les réponses qui ont résolu votre problème. C'est une voie commune pour reconnaître ceux qui vous ont aidé, et rend plus facile pour les autres visiteurs de trouver plus tard la résolution.

    mercredi 4 septembre 2013 10:58
    Propriétaire
  • Bonjour,

    J'essaye toujours de m'éloigner des tables temporaires pour éviter la duplication du temps d'exécution.

    Pour le moment j'utilise cette solution sauf si je trouverais d'autres solutions.

    Cordialement

    lundi 9 septembre 2013 07:28