DOC

Usando Transacciones COM+

By Leo Scott,2014-08-11 22:12
12 views 0
Usando Transacciones COM+

Usando Transacciones COM+

    en un Componente Visual Basic .NET

    Microsoft Windows 2000 es un servidor de aplicaciones que ofrece capacidades transaccionales a través de la tecnología COM+ (Component Object Model). En .NET a estas capacidades les llamaremos Enterprise Services (Servicios Empresariales), pues son funcionalidades que utilizamos en aplicaciones de rango empresarial.

    El namespace System.EnterpriseServices dentro del .NET Framework de Microsoft provee la funcionalidad para implementar procesamiento transaccional. Para obtener acceso a los servicios transaccionales de COM+, cree una clase siguiendo estos pasos:

    1. Abra Visual Studio .NET

    Start Programs Microsoft Visual Studio .NET Microsoft Visual Studio .NET

    2. Cree un nuevo proyecto de librería de clase (Class Library) con el nombre

    prjEnterprise en Visual Basic .NET.

    Visual Basic .NET creará una clase pública nombrada Class1.

    3. Adicione una referencia al proyecto, que apunte a la librería

    System.EnterpriseServices. Para ello, en la ventana del Solution Explorer, haga

     1

    Click Derecho sobre la carpeta References, y luego seleccione Add Reference

    desde el menú contextual. En el tabulado .NET, baje hasta encontrar

    System.EnterpriseServices. Dé Doble-Click sobre esta opción y asegúrese que

    aparece en la ventana Selected Components, y dé click en OK.

4. Use el enunciado Imports para el namespace System.EnterpriseServices y el

    namespace System.Data.SqlClient, de forma que más tarde, en el código, no tenga

    que estar calificando completamente las referencias a estos namespaces. Estos

    enunciados de importado deben aparecer antes de cualquier otro enunciado en su

    archivo de clase:

    Imports System.EnterpriseServices

    Imports System.Data.SqlClient

    5. Para utilizar los servicios transaccionales COM+, su clase, que renombrará a

    clsES, debe heredar la funcionalidad de ServicedComponent.

    Public Class clsES

     Inherits ServicedComponent

6. Se utiliza un atributo de Transaction para especificar el nivel de soporte

    transaccional para la clase:

    <Transaction(TransactionOption.Required> Public Class clsES

     2

     Inherits ServicedComponent

    7. Cree un método dentro de clsES llamado dbAccess que recibirá cuatro parámetros

    de entrada de tipo entero (integer). Los primeros dos parámetros proveerán un ID de producto y las unidades ordenadas de dicho producto. Los siguientes dos parámetros proveerán un ID de producto y las unidades en stock para dicho producto. El método llevará a cabo un set de operaciones de base de datos estos IDs de producto, que deben ser tratados como una sola transacción.

Public Sub dbAccess(ByVal pid1 as Integer, _

     ByVal onOrder as Integer, _

     ByVal pid2 as Integer, _

     ByVal inStock as Integer)

    8. En el método dbAccess, cree un objeto de conexión SQL hacia la base de datos Northwind, y luego abra dicha conexión. Las operaciones de base de datos utilizarán dicha base:

Dim Conn as New

    SqlConnection(“uid=sa;database=northwind;server=localhost”)

    Conn.Open

    9. Establezca un bloque Try para capturar cualquier error de base de datos que pueda ocurrir. Dichos errores deben ser capturados para ser capaces de abortar la transacción. El bloque Try incluirá dos operaciones de base de datos, cada una actualizando un campo en un registro específico de la tabla de productos (products)

    10. Lleve a cabo la primera actualización a la tabla de productos. Actualice el campo UnitsonOrder con el valor de onOrder para el producto del ID que fuera

    especificado en los primeros dos parámetros. Se utiliza un SQLcommand para correr el SQL de actualización:

Try

     Dim Cmd as SqlCommand

     Dim sqlString as String = _

     “update products set UnitsonOrder= “ & onOrder _

     & “ where productID = “ & pid1

     Cmd = New SqlCommand(sqlString,Conn)

     Cmd.ExecuteNonQuery()

    11. Lleve a cabo otra actualización adicional a la tabla de productos. Actualice el campo UnitsinStock con el valor de inStock para el producto del ID que fuera

    especificado en el tercer y cuatro parámetro de entrada. Se utiliza un SQLCommand para llevar a cabo esta actualización SQL:

sqlString = “update products set UnitsinStock = “ & inStock _

     & “ where productID = “ & pid2

    Cmd.CommandText = sqlString

    Cmd.ExecuteNonQuery()

     3

    12. Debido a que estas actualizaciones son parte de una transacción COM+, son

    “commited” como una unidad. El método setComplete de la clase contextUtil del

    namespace System.EnterpriseServices es usado para “commit” la transacción – en

    este caso, las dos actualizaciones (updates) si no se dispara (thrown) ningún

    error:

    ContextUtil.SetComplete()

13. Cerramos la conexión a la base de datos Northwind:

    Conn.Close()

    14. Cualquier error que ocurra al correr los comandos SQL deben ser atrapados, de

    forma que la transacción completa pueda ser abortada:

    Catch e As Exception

15. El método setAbort de la clase contextUtil del namespace

    System.EnterpriseServices es usado para abortar la transacción completa. Si la

    primera actualización es exitosa, pero la segunda falla, ninguna de las

    actualizaciones será posteada a la tabla de products. La excepción atrapada es

    enviada (thrown) al proceso llamante, indicando que la transacción falló:

     ContextUtil.SetAbort()

     Throw e

    End Try

16. Para que los componentes funcionen correctamente, deben tener un Strong Name.

    Siga estos pasos para generar un Strong Name y para firmar (sign) el Assembly

    con el Strong Name:

    a. Abra el Prompt de Comando de Visual Studio .NET. Para ello, de click en

    Start Programs Microsoft Visual Studio .NET Visual Studio .NET

    Tools Visual Studio .NET Command Prompt.

    b. En el prompt de comando, escriba: sn.exe k snEnterprise.snk para

    obtener un Strong Name para el Assembly.

     4

    Para más información de cómo firmar (sign) un Assembly con un Strong

    Name, refiérase a la documentación .NET Framework SDK.

    c. Copie snEnterprise.snk al folder del proyecto.

    d. En AssemblyInfo.vb adicion la siguiente línea de código antes o después

    de los otros enunciados de atributo del Assembly:

    <Assembly: AssemblyKeyFileAttribute(“..\..\snEnterprise.snk”)>

    e. Almacene y construya (build) su proyecto.

    Listado Completo del Código

Imports System.EnterpriseServices

    Imports System.Data.SqlClient

    <Transaction(TransactionOption.Required)> Public Class clsES

     Inherits ServicedComponent

     Public Sub dbAccess(ByVal pid1 As Integer, _

     ByVal onOrder As Integer, _

     ByVal pid2 As Integer, _

     ByVal inStock As Integer)

     Dim Conn As New

    SqlConnection("uid=sa;password=pass@word1;database=northwind;server=localhos

    t")

     Conn.Open()

     Try

     Dim Cmd As SqlCommand

     Dim sqlString As String = _

     "update products set UnitsonOrder = " & onOrder _

     & " where productID = " & pid1

     Cmd = New SqlCommand(sqlString, Conn)

     Cmd.ExecuteNonQuery()

     sqlString = _

     "update products set UnitsinStock = " _

     & inStock & " where productId = " & pid2

     Cmd.CommandText = sqlString

     Cmd.ExecuteNonQuery()

     ContextUtil.SetComplete()

     Conn.Close()

     Catch e As Exception

     ContextUtil.SetAbort()

     Throw e

     End Try

     End Sub

End Class

     5

Verifique que Funciona

Para probar este código, cree una aplicación de consola que utilice a la clase clsES. En

    uno de los casos a probar, la transacción es exitosa, y los campos UnitsonOrder y

    UnitsinStock para los productos especificados son actualizados. En el segundo caso, la

    actualización para UnitsonOrder para el producto específico es exitoso, pero la actualización para UnitsinStock del otro producto falla, pues se le especificará un número de producto inexistente en la tabla de Products. Esto resultará en una falla en la

    transacción, con lo que se ignora la transacción completa.

    1. Agregue una aplicación de consola llamada testES a su solución, de forma que su

    solución contenga tango el proyecto testES como el proyecto prjEnterprise. Para

    adicionar el nuevo proyecto, dé click en New File Project.

    2. Aparece una caja de diálogo New Project. Seleccione la carpeta Visual Basic en el

    “pane” de Project Types, y luego seleccione Console Application de las plantillas

    (templates). En la caja Name bajo el “pane” de los templates, tecle testES, que

    será el nombre del proyecto. Asegúrese de que el botón Add to solution, en la

    parte inferior de la caja de diálogo, esté seleccionada. Dé click en OK para

    adicionar este proyecto a la solución.

    3. Para que testES pueda probar clsES debrá agregar una referencia. En la ventana de

    Solution Explorer, haga click-derecho en la carpeta References del proyecto

    testES, el cual acaba de adicionar. Seleccione Add Reference. Aparece la caja de

    diálogo de Add Reference.

    4. Seleccione el tabulado Projects, y luego doble-click en prjEnterprise. Debe

    aparecer una referencia en Selected Components, en la parte baja de la caja de

    diálogo. Dé click en OK para adicionar la referencia al proyecto.

    5. Dé click derecho en la aplicación de consola, testES, y luego seleccione Set as

    Startup Project.

    6. En el menú de Debug, seleccione Windows. En el submenú, seleccione Immediate.

    Esto asegura que la ventana Immediate esté visible.

    7. Copie el siguiente código de prueba en el Module Module1, reemplazando los

    enunciados Sub Main y End Sub. El módulo debe aparecer como sigue:

    Sub Main()

     Dim myTest as New prjEnterprise.clsES()

     Try

     myTest.dbAccess(1,777,2,888)

     Debug.WriteLine(“Transacción 1 – EXITOSA”)

     6

     myTest.dbAccess(1,5,2,-20)

     Debug.WriteLine(“Transacción 2 – EXITOSA”)

     Catch

     Debug.WriteLine(“FALLA en Transacciones”)

     End Try

    End Sub

    8. Presione F5 para correr este código.

    9. En el código, en el paso 7, la primera llamada a dbAccess tendrá éxito, pues en la

    tabla Products existen un producto 1 y un producto 2. El campo UnitsonOrder

    para el producto 1 se actualiza a 777, y el campo UnitsinStock para el producto 2

    se actualiza a 888. Debido a que la transacción tiene éxito, la ventana Immediate

    debería desplegar el mensaje “Transacción 1 – EXITOSA”.

    La segunda llamada a dbAccess fallará, y por ello, ninguno de los enunciados de

    actualización (update) dentro de dbAccess hacia la tabla Products será posteada.

    A pesar que el primer producto (ID 1) podía actualizar su UnitsonOrder a 5, el

    segundo producto no pudo actualizar su campo UnitsinStock a -20. Debido a que

    en la definición de la tabla Product se ha definido una limitante (contraint) que no

    permite números negativos en UnitsinStock.

    Consecuentemente, esta segunda llamada a dbAccess falla, resultando en que la

    transacción entera falle. La tabla Products permanece como estaba antes de la

    llamada a dbAccess. El enunciado Catch maneja la notificación de la falla en la

    transacción del dbAccess, resultando en un mensaje desplegado en la ventana

    Immediate: “FALLA en Transacciones”

    Exaine el contenido de la tabla Products de la base Northwind usando el SQL Server Enterprise Manager. Cuando vea el producto 1, el campo UnitsonOrder tendrá el valor

    777; y para el producto 2, el campo UnitsinStock tendrá un valor de 888.

    Consecuentemente, la segunda llamada a dbAccess, la cual hubiera resultado en otros valores diferentes para estos campos, ha fallado.

     7

Report this document

For any questions or suggestions please email
cust-service@docsford.com