Actualización de una base de datos de SQL Server mediante el objeto SqlDataAdapter en Visual C++

En este artículo se presenta cómo usar el SqlDataAdapter objeto para actualizar una base de datos de SQL Server en Microsoft Visual C++.

Versión original del producto: Visual C++
Número de KB original: 308510

Resumen

El SqlDataAdapter objeto actúa como un puente entre un objeto ADO.NET DataSet y una base de datos de SQL Server. Es un objeto intermedio que puede usar para hacer lo siguiente:

  • Rellene un ADO.NET DataSet con los datos recuperados de una base de datos de SQL Server.
  • Actualice la base de datos para reflejar los cambios (inserciones, actualizaciones, eliminaciones) realizados en los datos mediante DataSet. En este artículo se proporcionan ejemplos de código .NET de Visual C++ para mostrar cómo se puede usar el SqlDataAdapter objeto para actualizar una base de datos de SQL Server con modificaciones de datos ejecutadas en un DataSet objeto que se rellena con datos de una tabla de la base de datos.

En este artículo se hace referencia al espacio de nombres System::Data::SqlClientbiblioteca de clases de .NET Framework .

Propiedades y objeto SqlDataAdapter

Las InsertCommandpropiedades , UpdateCommandy DeleteCommand del SqlDataAdapter objeto se usan para actualizar la base de datos con las modificaciones de datos ejecutadas en un DataSet objeto . Cada una de estas propiedades son SqlCommand objetos que especifican los comandos , UPDATEy DELETE TSQL correspondientes INSERTque se usan para publicar las DataSet modificaciones en la base de datos de destino. Los SqlCommand objetos asignados a estas propiedades se pueden crear manualmente en el código o se pueden generar automáticamente mediante el SqlCommandBuilder objeto .

En el primer ejemplo de código de este artículo se muestra cómo se puede usar el SqlCommandBuilder objeto para generar automáticamente la UpdateCommand propiedad del SqlDataAdapter objeto. El segundo ejemplo usa un escenario en el que no se puede usar la UpdateCommand generación automática de comandos y, por tanto, muestra el proceso por el que se puede crear y usar manualmente un SqlCommand objeto como propiedad de un SqlDataAdapter objeto.

Creación de la tabla de SQL Server de ejemplo

Para crear una tabla de SQL Server de ejemplo que se usará en los ejemplos de código .NET de Visual C++ documentados en este artículo, siga estos pasos:

  1. Abra SQL Server Analizador de consultas y, a continuación, conéctese a una base de datos en la que desea crear la tabla de ejemplo. Los ejemplos de código de este artículo usan la base de datos Northwind que incluye SQL Server.

  2. Ejecute las siguientes instrucciones T-SQL para crear una tabla de ejemplo denominada CustTest y, a continuación, inserte un registro en ella.

    Create Table CustTest
    (
        CustID int primary key,
        CustName varchar(20)
    )
    Insert into CustTest values(1,'John')
    

Ejemplo de código 1: comandos generados automáticamente

Si la SELECT instrucción para recuperar los datos utilizados para rellenar un DataSet se basa en una sola tabla de base de datos, puede aprovechar el CommandBuilder objeto para generar automáticamente las DeleteCommandpropiedades , InsertCommandy UpdateCommand de DataAdapter. Esto simplifica y reduce el código necesario para realizar INSERToperaciones , UPDATEy DELETE .

Como requisito mínimo, debe establecer la propiedad para que funcione la SelectCommand generación automática de comandos. El esquema de tabla recuperado por SelectCommand determina la sintaxis de las instrucciones , UPDATEy DELETE generadas INSERTautomáticamente.

SelectCommand También debe devolver al menos una clave principal o una columna única. Si no hay ninguno, se genera una InvalidOperation excepción y no se generan los comandos.

Para crear una aplicación de consola de Visual C++ .NET de ejemplo que muestre cómo usar el SqlCommandBuilder objeto para generar automáticamente las InsertCommandpropiedades de objeto , DeleteCommandy UpdateCommand SqlCommand para un SqlDataAdapter objeto, siga estos pasos:

  1. Inicie Visual Studio .NET y, a continuación, cree una nueva aplicación de C++ administrada. Asígnele el nombre updateSQL.

  2. Copie y pegue el código siguiente en updateSQL.cpp (reemplazando su contenido predeterminado):

    #include "stdafx.h"
    
    #using < mscorlib.dll>
    #using < System.dll>
    #using < System.Data.dll>
    #using < System.Xml.dll>
    
    using namespace System;
    using namespace System::Data;
    using namespace System::Data::SqlClient;
    
    #ifdef _UNICODE
        int wmain(void)
    #else
        int main(void)
    #endif
    {
        SqlConnection *cn = new SqlConnection();
        DataSet *CustomersDataSet = new DataSet();
        SqlDataAdapter *da;
        SqlCommandBuilder *cmdBuilder;
    
        //Set the connection string of the SqlConnection object to connect
        //to the SQL Server database in which you created the sample
        //table in Section 1.0
        cn->ConnectionString = "Server=server;Database=northwind;UID=login;PWD=password;";
        cn->Open();
    
        //Initialize the SqlDataAdapter object by specifying a Select command
        //that retrieves data from the sample table
        da = new SqlDataAdapter("select * from CustTest order by CustId", cn);
    
        //Initialize the SqlCommandBuilder object to automatically generate and initialize
        //the UpdateCommand, InsertCommand and DeleteCommand properties of the SqlDataAdapter
        cmdBuilder = new SqlCommandBuilder(da);
    
        //Populate the DataSet by executing the Fill method of the SqlDataAdapter
        da->Fill(CustomersDataSet, "Customers");
    
        //Display the Update, Insert and Delete commands that were automatically generated
        //by the SqlCommandBuilder object
        Console::WriteLine("Update command Generated by the Command Builder : ");
        Console::WriteLine("==================================================");
        Console::WriteLine(cmdBuilder->GetUpdateCommand()->CommandText);
        Console::WriteLine(" ");
        Console::WriteLine("Insert command Generated by the Command Builder : ");
        Console::WriteLine("==================================================");
        Console::WriteLine(cmdBuilder->GetInsertCommand()->CommandText);
        Console::WriteLine(" ");
        Console::WriteLine("Delete command Generated by the Command Builder : ");
        Console::WriteLine("==================================================");
        Console::WriteLine(cmdBuilder->GetDeleteCommand()->CommandText);
        Console::WriteLine(" ");
    
        //Write out the value in the CustName field before updating the data using the DataSet
        DataRow *rowCust = CustomersDataSet->Tables->Item["Customers"]->Rows->Item[0];
        Console::WriteLine("Customer Name before Update : {0} ", rowCust->Item["CustName"]);
    
        //Modify the value of the CustName field
        String *newStrVal = new String("Jack");
        rowCust->set_Item("CustName", newStrVal);
    
        //Modify the value of the CustName field again
        String *newStrVal2 = new String("Jack2");
        rowCust->set_Item("CustName", newStrVal2);
    
        //Post the data modification to the database
        da->Update(CustomersDataSet, "Customers");
    
        Console::WriteLine("Customer Name after Update : {0} ", rowCust->Item["CustName"]);
    
        //Close the database connection
        cn->Close();
    
        //Pause
        Console::ReadLine();
        return 0;
    }
    
  3. En el código que copió y pegó en el paso 2, modifique la línea de código de cadena de conexión para conectarse correctamente al equipo SQL Server, como se indica a continuación:

    cn.ConnectionString = "Server=server;Database=northwind;UID=login;PWD=password;";
    

    Después de ejecutar este código, puede conectarse con la instalación de SQL Server y, a continuación, iniciar sesión.

  4. Guarde y ejecute la aplicación. Se abrirá una ventana de consola y se mostrará la siguiente salida:

    Update command generated by the Command Builder:
    ==================================================
    UPDATE CustTest SET CustID = @p1 , CustName = @p2 WHERE ( (CustID = @p3)
    AND ((CustName IS NULL AND @p4 IS NULL)
    OR (CustName = @p5)))
    Insert command generated by the Command Builder :
    ==================================================
    INSERT INTO CustTest( CustID , CustName ) VALUES ( @p1 , @p2 )
    Delete command generated by the Command Builder :
    ==================================================
    DELETE FROM CustTest WHERE ( (CustID = @p1)
    AND ((CustName IS NULL AND @p2 IS NULL)
    OR (CustName = @p3)))
    Customer Name before Update : John
    Customer Name after Update : Jack2
    
  5. Presione cualquier tecla para descartar la ventana de la consola y detener la aplicación.

Ejemplo de código 2: crear e inicializar manualmente la propiedad UpdateCommand

La salida generada por el ejemplo de código 1 indica que la lógica para generar comandos automáticamente para UPDATE instrucciones se basa en la simultaneidad optimista. Es decir, los registros no están bloqueados para su edición y otros usuarios o procesos pueden modificarlos en cualquier momento. Dado que un registro puede haberse modificado después de que se devolvió de la SELECT instrucción pero antes de que se emita la UPDATE instrucción , la instrucción generada UPDATE automáticamente contiene una WHERE cláusula para que una fila se actualice solo si contiene todos los valores originales y no se ha eliminado. Esto se hace para asegurarse de que no se sobrescriben los nuevos datos. En los casos en los que una actualización generada automáticamente intenta actualizar una fila que se ha eliminado o no contiene los valores originales que se encuentran en , DataSetel comando no afecta a ningún registro y se produce .DBConcurrencyException

Si desea que UPDATE se complete independientemente de los valores originales, deberá establecer explícitamente para en lugar de depender de la UpdateCommandDataAdapter generación automática de comandos.

Para crear e inicializar manualmente la UpdateCommand propiedad del SqlDataAdapter objeto usado en el ejemplo de código 1, siga estos pasos:

  1. Copie y pegue el código siguiente (sobrescribiendo el código existente) en la Main() función dentro del archivo UpdateSQL.cpp de la aplicación de C++ creada en el ejemplo de código 1:

    SqlConnection *cn = new SqlConnection();
    DataSet *CustomersDataSet = new DataSet();
    SqlDataAdapter *da;
    SqlCommand *DAUpdateCmd;
    cn->ConnectionString = "Server=server;Database=northwind;UID=login;PWD=password;";
    cn->Open();
    da = new SqlDataAdapter("select * from CustTest order by CustId", cn);
    
    //Initialize the SqlCommand object that will be used as the DataAdapter's UpdateCommand
    //Notice that the WHERE clause uses only the CustId field to locate the record to be updated
    DAUpdateCmd = new SqlCommand("Update CustTest set CustName = @pCustName where CustId = @pCustId"
    , da->SelectCommand->Connection);
    
    //Create and append the parameters for the Update command
    DAUpdateCmd->Parameters->Add(new SqlParameter("@pCustName", SqlDbType::VarChar));
    DAUpdateCmd->Parameters->Item["@pCustName"]->SourceVersion = DataRowVersion::Current;
    DAUpdateCmd->Parameters->Item["@pCustName"]->SourceColumn = "CustName";
    
    DAUpdateCmd->Parameters->Add(new SqlParameter("@pCustId", SqlDbType::Int));
    DAUpdateCmd->Parameters->Item["@pCustId"]->SourceVersion = DataRowVersion::Original;
    DAUpdateCmd->Parameters->Item["@pCustId"]->SourceColumn = "CustId";
    
    //Assign the SqlCommand to the UpdateCommand property of the SqlDataAdapter
    da->UpdateCommand = DAUpdateCmd;
    da->Fill(CustomersDataSet, "Customers");
    
    DataRow *rowCust = CustomersDataSet->Tables->Item["Customers"]->Rows->Item[0];
    Console::WriteLine("Customer Name before Update : {0} ", rowCust->Item["CustName"]);
    
    //Modify the value of the CustName field
    String *newStrVal = new String("Jack");
    rowCust->set_Item("CustName", newStrVal);
    
    //Modify the value of the CustName field again
    String *newStrVal2 = new String("Jack2");
    rowCust->set_Item("CustName", newStrVal2);
    
    da->Update(CustomersDataSet, "Customers");
    Console::WriteLine("Customer Name after Update : {0} ", rowCust->Item["CustName"]);
    cn->Close();
    Console::ReadLine();
    return 0;
    
  2. Modifique la línea de código de cadena de conexión en el ejemplo de código anterior de la siguiente manera:

    cn.ConnectionString = "Server=server;Database=northwind;UID=login;PWD=password;";
    
  3. Si ya ha ejecutado el código en la sección de ejemplo de código 1 de este artículo, abra la tabla CustTesten SQL Server y, a continuación, cambie el valor custName del primer registro a John.

  4. Guarde y ejecute la aplicación. Se abrirá una ventana de consola y se mostrará la siguiente salida:

    Customer Name before Update : John
    Customer Name after Update : Jack2