La suppression ne fonctionne pas en transaction avec une insertion SQL

ado.net c# sqlbulkcopy sql-server-2008 transactions

Question

Je dois supprimer certains enregistrements de la table puis insérer certains enregistrements dans la même table. Ce processus de suppression et d'insertion doit être en transaction.

Ci-dessous est ce que j'ai fait.

 using (SqlConnection sqlConn = new SqlConnection(connectionString))
        {
            sqlConn.Open();
            using (SqlTransaction sqlTran = sqlConn.BeginTransaction())
            {
                string deleteQuery = "delete from dbo.MyTable where Col1 =" + colValue;
                SqlCommand sqlComm = new SqlCommand(deleteQuery, sqlConn,sqlTran);
                sqlComm.ExecuteNonQuery();
                using (SqlBulkCopy sqlcopy = new SqlBulkCopy(sqlConn, SqlBulkCopyOptions.Default, sqlTran))
                {
                    sqlcopy.BatchSize = 10;
                    sqlcopy.DestinationTableName = "MyTable";
                    try
                    {
                        sqlcopy.WriteToServer(dsDataSet.Tables[0]);
                        sqlTran.Commit();
                    }
                    catch (Exception ex)
                    {
                        sqlTran.Rollback();
                    }
                }
            }
        }

Mais, je suppose que l'opération de suppression n'est pas effectuée avant l'insertion, j'obtiens des erreurs en double. Quelqu'un peut-il aider?

Réponse acceptée

J'ai essayé votre exemple de code et cela a semblé fonctionner pour moi. J'ai créé un PK sur l'une des colonnes pour m'assurer qu'une insertion dupliquée provoquerait une erreur. Ensuite, je lance le code deux fois: la première fois, il introduit des données factices (aucune erreur n'est générée), la deuxième fois, il tente de supprimer les données, puis de les réinsérer dans la même transaction. D'après votre question, j'espérais obtenir une exception la deuxième fois, mais cela a fonctionné. Je ne suis pas sûr que cela compte, mais je suis en train d'exécuter SQL Server 2008 R2 SP1.

Voici le code de test complet que j'ai utilisé. Cela vous aidera peut-être à identifier votre problème.

Tout d'abord, le SQL pour créer un exemple de table:

CREATE TABLE [dbo].[MyTable](
    [Col1] [nvarchar](20) NOT NULL,
    [Col2] [nvarchar](20) NULL,
    [Col3] [nvarchar](30) NULL,
    CONSTRAINT [PK_MyTable] PRIMARY KEY CLUSTERED 
    (
        [Col1] ASC
    )
)

Et le C #:

public static void Main()
{
    DataTable t = new DataTable();
    t.Columns.Add(new DataColumn("Col1"));
    t.Columns.Add(new DataColumn("Col2"));
    t.Columns.Add(new DataColumn("Col3"));
    for (int i = 0; i < 5; i++)
    {
        var r1 = t.NewRow();
        r1["Col1"] = "1" + i.ToString();
        r1["Col2"] = "2" + i.ToString();
        r1["Col3"] = "3" + i.ToString();
        t.Rows.Add(r1);
    }
    t.AcceptChanges();
    var connectionString = new SqlConnectionStringBuilder();
    connectionString.DataSource = "localhost";
    connectionString.InitialCatalog = "testdb";
    connectionString.IntegratedSecurity = true;

    using (SqlConnection sqlConn = new SqlConnection(connectionString.ToString()))
    {
        sqlConn.Open();
        using (SqlTransaction sqlTran = sqlConn.BeginTransaction())
        {
            string deleteQuery = "delete from MyTable"; // just delete them all
            SqlCommand sqlComm = new SqlCommand(deleteQuery, sqlConn, sqlTran);
            sqlComm.ExecuteNonQuery();
            using (SqlBulkCopy sqlcopy = new SqlBulkCopy(sqlConn, SqlBulkCopyOptions.Default, sqlTran))
            {
                sqlcopy.BatchSize = 10;
                sqlcopy.DestinationTableName = "MyTable"; 
                try
                {
                    sqlcopy.WriteToServer(t);
                    sqlTran.Commit();
                }
                catch (Exception ex)
                {
                    sqlTran.Rollback();
                }
            }
        }
    }

}

Mise à jour de votre question Au fait, vous n'avez pas reçu d'erreur car le 23/11/2011 a été évalué comme une expression mathématique ('/' est une division), ce qui a donné la valeur 0, qui a ensuite été implicitement convertie en date / heure 1900/01/01. Essayez d'exécuter la requête "sélectionnez CONVERTIR (datetime, 23/11/2011)" et vous verrez ce que je veux dire.



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi