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
DataSetcon 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 elSqlDataAdapterobjeto para actualizar una base de datos de SQL Server con modificaciones de datos ejecutadas en unDataSetobjeto 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::SqlClient.NET Framework biblioteca de clases .
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:
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.
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 , UDPATEy 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:
Inicie Visual Studio .NET y, a continuación, cree una nueva aplicación de C++ administrada. Asígnele el nombre updateSQL.
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; }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.
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 : Jack2Presione 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 UpdateCommand en lugar de basarse en la DataAdapter 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:
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;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;";Si ya ha ejecutado el código en la sección de ejemplo de código 1 de este artículo, abra custTesttable en SQL Server y, a continuación, cambie el valor custName en el primer registro a John.
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