Cómo utilizar transacciones COM + en un componente de Visual C++ .NET o en un componente de Visual C++ 2005

Seleccione idioma Seleccione idioma
Id. de artículo: 815814 - Ver los productos a los que se aplica este artículo
Expandir todo | Contraer todo

En esta página

RESUMEN

En este artículo paso a paso se describe cómo utilizar COM + (servicios de componentes) transacciones en una clase de Microsoft Visual C++ .NET o en una clase de Microsoft Visual C++ 2005. Un conjunto de operaciones de base de datos se considera una unidad. Todas las operaciones se realice correctamente o, si se produce un error en una operación, falla la transacción completa. En el último caso, no se registran las operaciones de base de datos que se intentaron ejecutar a la base de datos subyacente.

Requisitos

En este artículo se supone que está familiarizado con los temas siguientes:
  • Conceptos transaccionales y de procesamiento
  • COM + (servicios de componentes)

Servicios de transacción COM +

Puede implementar procesamiento con el espacio de nombres System.EnterpriseServices en Microsoft .NET Framework de transacciones. Para tener acceso a COM + servicios transaccionales, crear una clase. Para ello, siga estos pasos:
  1. Inicie Visual Studio .NET o Visual Studio 2005.
  2. En el menú archivo , seleccione nuevo y, a continuación, haga clic en proyecto .
  3. En Tipos de proyecto , haga clic en Proyectos de Visual C++ y, a continuación, haga clic en Biblioteca de clases (. NET) en plantillas . Nombre prjEnterprise el proyecto.

    Nota En Visual Studio 2005, haga clic en Visual C++ en Tipos de proyecto y, a continuación, haga clic en Biblioteca de clases en plantillas .
  4. En el Explorador de soluciones, haga clic con el botón secundario en referencias y, a continuación, haga clic en Agregar referencia .
  5. Haga clic en el cuadro de diálogo Agregar referencia en la ficha de NET .
  6. Haga doble clic en System.EnterpriseServices en nombre del componente .
  7. Asegúrese de que System.EnterpriseServices aparece bajo Componentes seleccionados y, a continuación, haga clic en Aceptar .
  8. Agregue el código siguiente antes de cualquier otra instrucción en el archivo prjEnterprise.h:
    using namespace System;
    using namespace System::Data;
    using namespace System::Data::SqlTypes;
    using namespace System::Data::Common;
    using namespace System::EnterpriseServices;
    using namespace System::Data::SqlClient;
    
  9. Agregar una nueva clase que se denomina clsES en el archivo prjEnterprise.h.
  10. Para utilizar los servicios transaccionales de COM +, asegúrese de que la clase ( clsES ) hereda funciones de la clase ServicedComponent como sigue:
    public __gc class clsES:public ServicedComponent
    
  11. Utilice un atributo de transacción para especificar el nivel de compatibilidad transaccional de la clase como sigue:
    [Transaction(TransactionOption::Required,Timeout=5)]public __gc class clsES:public ServicedComponent
    
  12. Cree un método de la clase clsES que recibe cuatro parámetros de entrada de número entero. Nombre de la clase dbAccess. Los dos primeros parámetros proporcionan un identificador de producto y las unidades en pedido para ese producto. Los dos parámetros proporcionan un identificador de producto y las unidades en existencias para ese producto. Este método realiza un conjunto de operaciones de base de datos en estos identificadores de producto especificado en el que se tratarán como una transacción:
    public:	void dbAccess(int pID1, int onOrder, int pID2, int inStock)
  13. En el método dbAccess , cree un objeto de conexión de SQL para Northwind la base de datos y, a continuación, abrir la conexión. Producirse operaciones de base de datos mediante la siguiente base de datos:
    SqlConnection * Conn = new SqlConnection("user id=<username>;password=<password>;Initial Catalog=northwind;Data Source=<Your SQL Server name>;");
    Conn->Open();
    Nota Recuerde cambiar los parámetros de cadena de conexión para reflejar los valores correctos para el servidor de SQL Server.
  14. Establecer un bloque try para capturar las excepciones que pueden producirse durante el procesamiento de base de datos. Debe detectar estas excepciones para anular la transacción. El bloque try incluye dos operaciones de base de datos. Cada operación actualiza un campo diferente en un registro de tabla de productos especificado.
    try { 
    
  15. Realizar la primera actualización en la tabla products. Actualizar el campo UnitsOnOrder con valor onOrder del producto con el identificador, como se especifica en los dos primeros parámetros de entrada. Utilice el siguiente comando SQL para ejecutar esta actualización SQL:
    SqlCommand * sqlCommand = new SqlCommand("UPDATE Products SET UnitsonOrder = @onOrderString WHERE productID = @pID1String ", Conn);
    sqlCommand->Parameters->Add(new SqlParameter("@onOrderString",SqlDbType::VarChar ,
    	40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,onOrder.ToString()));
    sqlCommand->Parameters->Add(new SqlParameter("@pID1String", SqlDbType::VarChar,
    	40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,pID1.ToString()));
    sqlCommand->ExecuteNonQuery();
    
  16. Realizar otra actualización en la tabla products. Actualizar el campo UnitsInStock con la inStock valor para el producto con el identificador, como se especifica en los parámetros de entrada de tercer y cuarto. Utilice el siguiente comando SQL para ejecutar esta actualización SQL: sqlCommand
    sqlCommand->Parameters->Add(new SqlParameter("@inStockString",SqlDbType::VarChar ,
    	40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,inStock.ToString()));
    sqlCommand->Parameters->Add(new SqlParameter("@pID2String", SqlDbType::VarChar,
    	40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,pID2.ToString()));
    sqlCommand->ExecuteNonQuery();
    
  17. Dado que estas actualizaciones son parte de una transacción, son confirmadas como una unidad. Se utiliza el método setComplete de la clase contextUtil desde el espacio de nombres System.EnterpriseServices para confirmar la transacción (en este caso las dos actualizaciones) si no se producen errores:
    ContextUtil::SetComplete(); 
    
  18. Utilice el siguiente código para cerrar la conexión a la base de datos Northwind:
    Conn->Close(); }
    
  19. Debe detectar las excepciones que ocurren mientras se ejecuta los comandos SQL para que se puede anular la transacción completa:
    catch(Exception * e){ 
    
  20. Se utiliza el método setAbort de la clase contextUtil desde el espacio de nombres System.EnterpriseServices para anular la transacción completa. Si la primera actualización es correcta y la segunda actualización falla, se registra ninguna actualización en la tabla products. Se produce la excepción detectada al llamador, que indica que la transacción se produjo un error:
    ContextUtil::SetAbort();
    throw e; }
    
  21. Para que este componente para que funcione correctamente, el componente debe tener un nombre seguro. Generar un nombre seguro y, a continuación, firme el ensamblado con nombre seguro. Para ello, siga estos pasos:
    1. En el símbolo de comandos de Visual Studio .NET, escriba sn.exe -k snEnterprise.snk para crear un archivo de clave. Para obtener más información acerca de firma de ensamblados con nombres seguros, consulte la documentación de .NET Framework SDK.
    2. Copiar snEnterprise.snk a su carpeta del proyecto.
    3. En AssemblyInfo.vc, agregar la siguiente línea de código antes o después otras instrucciones de atributo de ensamblado:
      [assembly:AssemblyKeyFileAttribute("..\\snEnterprise.snk")]; 
    4. Guardar y, a continuación, generar el proyecto.

Listado de código completo

Nota Remember to change your connection string parameters to reflect the correct values for your SQL Server server.
#pragma once

using namespace System;
using namespace System::Data;
using namespace System::Data::SqlTypes;
using namespace System::Data::Common;
using namespace System::EnterpriseServices;
using namespace System::Data::SqlClient;

namespace prjEnterprise
{
	
	[Transaction(TransactionOption::Required,Timeout=5)]
	public __gc class clsES:public ServicedComponent
	{
	public:	SqlConnection * Conn;

	public:	void dbAccess(int pID1, int onOrder, int pID2, int inStock)
		{
			try
			{			
				SqlConnection * Conn = new SqlConnection("user id=<username>;password=<password>;Initial Catalog=northwind;Data Source=<Your SQL Server name>;");
				Conn->Open();
				
				SqlCommand * sqlCommand = new SqlCommand("UPDATE Products SET UnitsonOrder = @onOrderString WHERE productID = @pID1String ", Conn);
				sqlCommand->Parameters->Add(new SqlParameter("@onOrderString",SqlDbType::VarChar ,
					40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,onOrder.ToString()));
				sqlCommand->Parameters->Add(new SqlParameter("@pID1String", SqlDbType::VarChar,
					40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,pID1.ToString()));
				sqlCommand->ExecuteNonQuery();
				
				sqlCommand->CommandText = "UPDATE Products SET UnitsinStock = @inStockString WHERE productID = @pID2String" ;
				sqlCommand->Parameters->Add(new SqlParameter("@inStockString",SqlDbType::VarChar ,
					40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,inStock.ToString()));
				sqlCommand->Parameters->Add(new SqlParameter("@pID2String", SqlDbType::VarChar,
					40,ParameterDirection::Input,true,0,0,"Description",DataRowVersion::Current,pID2.ToString()));
				sqlCommand->ExecuteNonQuery();

				ContextUtil::SetComplete();
				Conn->Close();
			}
			catch(Exception * e)
			{
				ContextUtil::SetAbort();
			
				throw e;
			}			
		}
	};


}
Nota debe agregar common language runtime admite opción de compilador (/ CLR: oldSyntax) en Visual C++ 2005 para compilar correctamente el ejemplo de código anterior. Para agregar la opción de compilador de common language runtime compatibilidad en Visual C++ 2005, siga estos pasos:
  1. Haga clic en proyecto y, a continuación, haga clic en <ProjectName> propiedades .

    Nota <ProjectName> es un marcador de posición para el nombre del proyecto.
  2. Expanda Propiedades de configuración y, a continuación, haga clic en General .
  3. Haga clic para seleccionar compatible con Common Language Runtime, sintaxis antigua (/ CLR: oldSyntax) en la configuración de proyecto compatibilidad con Common Language Runtime en el panel derecho, haga clic en Aplicar y, a continuación, haga clic en Aceptar .
Para obtener más información acerca de common language runtime admite (opción del compilador), visite el siguiente sitio Web de Microsoft:
/ clr (Common Language Runtime Compilation)
http://msdn2.microsoft.com/en-us/library/k8d11d4s.aspx

Comprobar que funciona

Para probar este código, cree un proyecto de aplicación de consola que utiliza la clase clsES . En un caso, una transacción tiene éxito y se actualizan los campos UnidadesEnPedido y UnidadesEnExistencias del producto especificado. En el segundo caso, la actualización para el campo UnitsOnOrder para un producto especificado se realiza correctamente, pero la actualización para el campo unidades en existencia para un producto falla porque el número de producto especificada no existe en la tabla productos. Esto provoca un error de transacción y se omite la transacción.
  1. Iniciar Visual Studio .NET o Visual Studio 2005.
  2. En el menú archivo , seleccione nuevo y, a continuación, haga clic en proyecto .
  3. En Tipos de proyecto , haga clic en Proyectos de Visual C++ y, a continuación, haga clic en Aplicación de consola (. NET) en plantillas .

    Nota En Visual Studio 2005, haga clic en Visual C++ en Tipos de proyecto y, después, haga clic en Aplicación de consola CLR en plantillas .
  4. En el cuadro de texto nombre , escriba testES . Asegúrese de que está seleccionada la opción Agregar a solución .
  5. Haga clic en Aceptar para agregar este proyecto a la solución.
  6. Para que testES probar prjEnterprise , debe agregar una referencia. En el Explorador de soluciones, haga clic con el botón secundario en referencias en testES (que acaba de agregar) y, a continuación, haga clic en Agregar referencia .
  7. Aparecerá el cuadro de diálogo Agregar referencia . En la ficha proyectos , haga doble clic en prjEnterprise .
  8. Una referencia aparece bajo seleccionado componentes . Haga clic en Aceptar para agregar esta referencia al proyecto.
  9. Agregue una referencia al proyecto al espacio de nombres System.EnterpriseServices . En el Explorador de soluciones, haga clic con el botón secundario en referencias y, a continuación, haga clic en Agregar referencia .
  10. Aparecerá el cuadro de diálogo Agregar referencia . En Nombre de componente en la ficha .NET , haga doble clic en System.EnterpriseServices .
  11. Asegúrese de que System.EnterpriseServices aparece bajo Componentes seleccionados . Haga clic en Aceptar .
  12. Haga clic con el botón secundario del mouse en testES y, a continuación, haga clic en establecer como proyecto de inicio .
  13. Pegue el siguiente código de origen en la función _tmain() de la clase testES :
    prjEnterprise::clsES * myTest = new prjEnterprise::clsES();	
    try 
    {
    	myTest->dbAccess(1, 777, 2, 888);
    	Console::WriteLine("TRANSACTION ONE -- SUCCESS");
    
    		myTest->dbAccess(1, 5, 2, -20);
    	Console::WriteLine("TRANSACTION TWO -- SUCCESS");
    }
    catch (Exception * e)
    {
    	Console::WriteLine("TRANSACTION FAILURE");
    	//Console::WriteLine("Error Message: {0}",e->Message);	 
    	//uncomment this line if you must get detailed error information
    }
    
  14. Presione F5 para ejecutar el código de prueba.

    En el código en el paso 7, la primera llamada a dbAccess se realiza correctamente. Producto 1 y 2 del producto se encuentran en la tabla productos. El campo onOrder para producto 1 se actualiza a 777 y el inStock campo para el producto 2 se actualiza a 888 . Debido a esta transacción se realizó correctamente, recibirá el mensaje siguiente en la ventana de resultados:
    TRANSACCIÓN UNO - ÉXITO
    La segunda llamada a dbAccess producirá errores. Por lo tanto, se registra ninguna instrucción de actualización en dbAccess a la tabla productos en la base de datos. Aunque producto 1 podría tener su campo UnitsOnOrder actualizado a 5 , producto 2 no puede tener su campo UnitsInStock sea -20 . Debido a una restricción definida en la definición de tabla de productos, de UnidadesEnExistencias no se permite con números negativos. Por tanto, esta llamada a dbAccess falla y toda la transacción falla. La tabla productos permanece tal y como era antes de la llamada a dbAccess . La instrucción catch controla la notificación del error de transacción de dbAccess y recibirá el siguiente mensaje de error en la ventana de resultados:
    ERROR DE TRANSACCIÓN
  15. Examine el contenido de la tabla Products de Northwind utilizando el Administrador corporativo de SQL Server. Al ver producto 1, el campo UnitsOnOrder es igual a 777 . Cuando ve producto 2, el campo UnitsInStock es 888 . Por lo tanto, la segunda llamada a dbAccess (que habría ocasionado distintos valores para estos campos) produce un error.

Solución de problemas

  • Asegúrese de que cualquier proyecto que utiliza los servicios COM + tiene un nombre seguro.
  • Cualquier clase que utiliza los servicios COM + debe heredar del componente revisado. El componente se encuentra en el espacio de nombres System.EnterpriseServices .
  • Durante la depuración, una transacción puede tiempo de espera antes de que se confirme o anulado. Para evitar un tiempo de espera, utilice una propiedad de tiempo de espera en el atributo de transacción. En el ejemplo siguiente, el método asociado tiene 1200 segundos para finalizar cualquier transacción hasta que se agota:
    [Transaction(TransactionOption::Required,Timeout=1200)]
    
  • Puede recibir algunos excepciones inesperadas al ejecutar el código. Para recibir más información acerca de estas excepciones, quite el comentario de las dos últimas líneas en el paso 13:
    Console::WriteLine("Error Message: {0}",e->Message);
    uncomment this line if you must get detailed error information

Referencias

Para obtener información adicional, visite los siguientes sitios Web de Microsoft Developer Network (MSDN):
COM + Integration: How .NET Enterprise Services pueden ayudarle generar aplicaciones distribuidas
Componentes facilitados como servicio

Propiedades

Id. de artículo: 815814 - Última revisión: miércoles, 14 de noviembre de 2007 - Versión: 3.2
La información de este artículo se refiere a:
  • Microsoft Visual C++ 2005 Express Edition
  • Microsoft Visual C++ .NET 2003 Standard
Palabras clave: 
kbmt kbsqlclient kbcomplusqc kbcode kbhowtomaster kbhowto KB815814 KbMtes
Traducción automática
IMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.
Haga clic aquí para ver el artículo original (en inglés): 815814

Enviar comentarios

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com