Eliminar no funciona en la transacción con inserto masivo de SQL

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

Pregunta

Necesito eliminar algunos registros de la tabla y luego insertar algunos registros en la misma tabla. Este proceso de eliminación e inserción debe estar en la transacción.

A continuación es lo que hice.

 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();
                    }
                }
            }
        }

Pero, supongo que como la operación de eliminación no se realiza antes de la inserción, obtengo errores duplicados de clave. ¿Alguien puede ayudar?

Respuesta aceptada

Probé su código de muestra, y pareció funcionar para mí. Creé una PK en una de las columnas para asegurarme de que una inserción duplicada arrojara un error. Luego ejecuto el código dos veces: la primera vez que ingresa algunos datos ficticios (no se producen errores), la segunda vez intenta eliminar los datos y luego reinsertarlos dentro de la misma transacción. De su pregunta, esperaba obtener una excepción la segunda vez, pero funcionó. No estoy seguro de que importe, pero estoy ejecutando SQL Server 2008 R2 SP1.

Aquí está el código de prueba completo que utilicé, tal vez le ayude a identificar su problema.

Primero el SQL para crear una tabla de muestra:

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
    )
)

Y el 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();
                }
            }
        }
    }

}

Actualización sobre su pregunta Por cierto, no recibió un error porque el 23/11/2011 se evaluó como una expresión matemática ('/' es división), lo que dio como resultado el valor 0, que luego se convirtió implícitamente en una fecha y hora como 1900/01/01. Intente ejecutar la consulta "seleccione CONVERTIR (fecha y hora, 23/11/2011)" y verá lo que quiero decir.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué