System.Collections.ListofTips

January 31, 2008

Introducción a XML

Filed under: ADO.net, ASP.net, C# — José Franco @ 12:45 am

Para manipulacion de Xml, entra en juego System.Xml

Pero partamos desde lo basico, que es XML? Es un metalenguaje extensible de etiquetas desarrollado por la W3C. Mas que nada fue una proposicion, a tomar un estandar para el intercambio de información entre diferentes plataformas.

En es una tecnologia muy simple, pero que hace posible interoperabilidades bastante importantes en distintos ambientes, ya que lo toman como un lenguaje para hablar por ejemplo un WebServices, tanto como una aplicación WinForm en C# como una aplicación de Consola de Lynx.

Los documentos XML debe seguir una estructura estrictamente jerárquica con lo que respecta a las etiquetas que delimitan sus elementos. Una etiqueta debe estar correctamente incluida en otra. Ademas que solo se permite un elemento raiz, osea solo puede tener un solo elemento inicial.

Hay detalles como, los valores de los atributos, deben estar encerrados entre comillas simples o dobles, no es un lenguaje flexible como es el html, es mucho mas estricto. Otro detalle, es que es Case-Sensitive.

El Web.Config, es un ejemplo claro de XML.
Nosotros tambien podria tener definida la estructura del XML, por DTD, XSD, XDR o XLS/XLST, vamos a ver puntualmente cada caso:

DTD (Document Type Definition):

Su función básica es la descripción del formato de datos, para usar un formato común y mantener la consistencia entre todos los documentos que utilicen la misma DTD. De esta forma, dichos documentos, pueden ser validados, conocen la estructura de los elementos y la descripción de los datos que trae consigo cada documento, y pueden además compartir la misma descripción y forma de validación dentro de un grupo de trabajo que usa el mismo tipo de información.

Una DTD describe:

  • Elementos: indican qué etiquetas son permitidas y el contenido de dichas etiquetas.
  • Estructura: indica el orden en que van las etiquetas en el documento.
  • Anidamiento: indica qué etiquetas van dentro de otras.

Ejemplo de un DTD:

<!ELEMENT lista_de_personas (persona*)>
<!
ELEMENT persona (nombre, fechanacimiento?, sexo?, numeroseguridadsocial?)>
<!
ELEMENT nombre(#PCDATA) >
<!
ELEMENT fechanacimiento(#PCDATA) >
<!
ELEMENT sexo(#PCDATA) >
<!
ELEMENT numeroseguridadsocial(#PCDATA)>


Observándolo línea a línea nos dice:

  • <lista_de_personas> es un nombre de elemento válido. El * indica que pueden haber 0 o más elementos de persona.
  • <persona> es un nombre de elemento válido. Éste contiene obligatoriamente el elemento nombre mientras que el resto son opcionales. Y lo son porque nos lo indica el símbolo’?’
  • <nombre> es un nombre de elemento válido. Contiene caracteres.
  • <sexo> es un nombre de elemento válido. Contiene caracteres.
  • <fechanacimiento> es un nombre de elemento válido.
  • <numeroseguridadsocial> es un nombre de elemento válido.

Un ejemplo de un fichero XML que hace uso de esta DTD:

<?xml version=1.0 encoding=iso-8859-1?>
<!
DOCTYPE lista_de_personas SYSTEM ejemplo.dtd>
<
lista_de_personas>
<
persona>
<
nombre>José García</nombre>
<
fechanacimiento>25/04/1984</fechanacimiento>
<
sexo>Varón</sexo>
</
persona>
</
lista_de_personas>

Tienen mas información aca:
http://es.wikipedia.org/wiki/DTD

http://www.zvon.org/xxl/DTDTutorial/General_spa/book.html

http://www.xeml.net/ccdtdxml.html

http://gutfeldt.ch/matthias/articles/doctypeswitch/table.html

XSD (Xml Schema Definition): Basado en la gramática y pensado para proporcionar una mayor potencia expresiva que la DTD, más limitadas en la descripción de los documentos a nivel formal.

Los documentos esquema (usualmente con extensión .xsd de XML Schema Definition (XSD)) se concibieron como una alternativa a las DTD, más compleja, intentando superar sus puntos débiles y buscar nuevas capacidades a la hora de definir estructuras para documentos XML. La principal aportación de XML Schema es el gran número de los tipos de datos que incorpora. De esta manera, XML Schema aumenta las posibilidades y funcionalidades de aplicaciones de procesado de datos, incluyendo tipos de datos complejos como fechas, números y strings.

os esquemas se construyen a partir de diferentes tipos de componentes:

  • Elemento (element)
  • Atributo (attribute)
  • Tipo simple (simple type)
  • Tipo complejo (complex type)
  • Notación (notation)
  • Grupo modelo nombrado (named model group)
  • Grupo de atributos (attribute group)
  • Restricción identidad (identity constraint)

Estos componentes ofrecen la posibilidad de combinar características de alto o bajo nivel:

  • Alto nivel: Se encargan de ofrecer un significado semántico del contenido del documento. Analizan el contenido y extraen de él un significado. Éste puede estar predefinido en la declaración del esquema o se puede extraer de la misma estructura.
  • Bajo nivel: Son características más concretas del documento que están incluidos en los diferentes campos del esquema y se accede a ellas de manera directa. Son los que se comparan directamente con el criterio de búsqueda definido y halla palabras concretas en la definición de los esquemas.

XML Schema supera muchas de las limitaciones y debilidades de las DTDs. Fue diseñado completamente alrededor de namespaces y soporta tipos de datos típicos de los lenguajes de programación, como también tipos personalizados simples y complejos. Un esquema se define pensando en su uso final.

Un ejemplo de XSD seria:

<?xml version=1.0 encoding=UTF-8?>
<
xsd:schema xmlns:xsd=http://www.w3.org/2001/XMLSchema>
<
xsd:element name=Libro>
<
xsd:complexType>
<
xsd:sequence>
<
xsd:element name=Título type=xsd:string/>
<
xsd:element name=Autores type=xsd:string maxOccurs=10/>
<
xsd:element name=Editorial type=xsd:string/>
</
xsd:sequence>
<
xsd:attribute name=precio type=xsd:double/>
</
xsd:complexType>
</
xsd:element>
</
xsd:schema>

Mas información:

http://es.wikipedia.org/wiki/XML_Schema

XDR (Xml Data Reduced): Es un formatode definición de esquemas tambien para XML.

Mas información:

http://www.ltg.ed.ac.uk/~ht/XMLData-Reduced.htm

XSL, XSLT:Es un estandar de la organización W3C que presenta una forma de transformar documentos XML en otros e incluso a formatos que no son XML. Las hojas de estilo (aunque el termino de hojas de estilo no se aplica sobre la función directa del XSLT) XSLT realizan la transformación del documento utilizando una o varias reglas de plantilla: unidas al documento fuente a transformar, esas reglas de plantilla alimentan a un procesador de XSLT, el cual realiza las transformaciones deseadas colocando el resultado en un archivo de salida o, como en el caso de una página web, directamente en un dispositivo de presentación, como el monitor de un usuario.

Actualmente, XSLT es muy usado en la edición web, generando páginas HTML o XHTML. La unión de XML y XSLT permite separar contenido y presentación, aumentando así la productividad.

Las clases mas importantes para el tratamiento de XML, son : XpathNavigator, XmlDocument, XmlDataDocument, XpathDocument, XslTransform, XmlTextReader, XmlTextWriter

Un dato importante que XmlDataDocument hereda de XmlDocument.

XPathDocument es una cache de sólo lectura que viene bien para usar con consultas XPath.

XmlConver es una clase con un montón de métodos estáticos que permiten realizar conversiones de datos acordes con estándares Xml.

XPathNavigator, permite recorrer un documento Xml de manera eficiente usando consultas XPath.

XmlNodeReader: Permite un acceso secuencial (forward-only) para recorrer un documento a partir de un nodo determinado.

XmlTextReader: Proporciona acceso secuencial (no chacheado) a un documento xml.

XmlTextWriter: Proporciona acceso secuencial, no chacheado para la escritura de documentos xml.

XmlReader: Permite leer y validar contenido conforme a un DTD, XDR o XSD.

XslTransform: Permite transformar un documento Xml a partir de lo especificado en otro XSL.

Veamos algunos ejemplos de XML, pero en codigo…

Si yo quisiera generar esta salida…

<?xml version=1.0 encoding=utf-8?>
<
Customers>
<
Customer CustomerId=000>
<
Name>Name 0</Name>
</
Customer>
</
Customers>

Nuesto Codigo seria en una aplicación de consola:


1
using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Xml;
5
6
namespace ConsoleApplication1
7 {
8 class Program
9 {
10  static void Main(string[] args)
11 {
12 XmlDocument xmlDoc = new XmlDocument();
13 xmlDoc.AppendChild(xmlDoc.CreateXmlDeclaration(“1.0″, “utf-8″, null));
14 XmlElement rootNode = xmlDoc.CreateElement(“Customers”);
15 xmlDoc.AppendChild(rootNode);
16 for (int i = 0; i < 1; i++)
17 {
18 XmlElement customerElement = xmlDoc.CreateElement(“Customer”);
19 XmlAttribute idAttribute = xmlDoc.CreateAttribute(“CustomerId”);
20 idAttribute.Value = i.ToString(“000″);
21 customerElement.Attributes.Append(idAttribute);
22
23 XmlElement nameElement = xmlDoc.CreateElement(“Name”);
24 nameElement.InnerText = string.Format(“Name {0}”, i.ToString());
25 customerElement.AppendChild(nameElement);
26 rootNode.AppendChild(customerElement);
27  }
28 string fileName = “C:\\Customers.xml”;
29 xmlDoc.Save(fileName);
30 Console.WriteLine(“Archivo generado…”);
31 Console.ReadLine();
32 }
33 }
34 }

Si quisieramos leelo seria….

1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Xml;
5
6 namespace ConsoleApplication1
7 {
class Program
9 {
10 static void Main(string[] args)
11 {
12 XmlDocument xmlDoc = new XmlDocument();
13 string fileName = “C:\\Customers.xml”;
14 xmlDoc.Load(fileName);
15 foreach (XmlElement element in xmlDoc.DocumentElement.ChildNodes)
16 {
17 Console.WriteLine(“Atributo Id->” + element.Attributes[“CustomerId”].Value);
18 XmlNodeList childNodes = element.GetElementsByTagName(“Name”);
19 Console.WriteLine(“Nodo Hijo->” + childNodes[0].InnerText);
20 }
21 Console.WriteLine(“Se termino de recorrer el archivo”);
22 Console.ReadLine();
23
24 }
25 }
26 }

Y nuestra salida


Este metodo usa DOM, pero para un metodo de lectura, es mas optimo y consume menos recursos la clase XpathNavigator.

Para este caso seria:

1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Xml;
5 using System.Xml.XPath;
6
7 namespace ConsoleApplication1
8 {
class Program
10 {
11  static void Main(string[] args)
12 {
13 XmlDocument xmlDoc = new XmlDocument();
14 string fileName = “C:\\Customers.xml”;
15 xmlDoc.Load(fileName);
16 XPathNavigator xPathNav = xmlDoc.CreateNavigator();
17 xPathNav.MoveToFirstChild();
18 xPathNav.MoveToFirstChild();
19 do
20 {
21 xPathNav.MoveToFirstAttribute();
22 Console.WriteLine(“Atributo Id->” + xPathNav.Value);
23 //Podemos obtener el valor en Int si lo quisieramos
24 int _post=xPathNav.ValueAsInt;
25 xPathNav.MoveToParent();
26 xPathNav.MoveToFirstChild();
27 Console.WriteLine(“Nodo Hijo->”+xPathNav.Value);
28 xPathNav.MoveToParent();
29 }
30 while (xPathNav.MoveToNext());
31 Console.WriteLine(“Se termino de recorrer el archivo”);
32 Console.ReadLine();
33
34
35 }
36 }
37 }

Despues, publico algo mas interesante sobre XLST, etc… Saludos.

January 24, 2008

Registrar Northwind en SQL Express 2005

Filed under: ADO.net, Resources, Sql Server — José Franco @ 1:47 am

Para los ejemplos, se puede practicar con la base de Northwind, lamentablemente no se instalan por defecto en Sql Server 2005.

Bajar desde el link

http://www.microsoft.com/downloads/details.aspx?FamilyId=06616212-0356-46A0-8DA2-EEBC53A68034&displaylang=en

Si hacen la instalacion por defecto, les deja los archivos en

C:\SQL Server 2000 Sample Databases

La pueden registrar con el SQL Server Management Studio Express

Que lo descargan en caso de no tenerlo, desde

http://www.microsoft.com/downloads/details.aspx?FamilyID=C243A5AE-4BD1-4E3D-94B8-5A0F62BF7796&displaylang=es

Cuando abran el Management, les va a pedir los datos del servidor que en esta caso seria:


Y finalmente en el administrador


Una vez ahi, solo deben explorar a donde esta localizado el archivo .mdf


Aceptamos, y nos va a mostrar las base de datos que vamos a adjuntar


Y Finalmente ya la tendrian registrada


Si tienen otros usuarios, deberian configurar los permisos, y demas.

January 23, 2008

Introducción a ADO.net

Filed under: ADO.net — José Franco @ 1:42 am

Les dejo un articulo de introducción que hice hace un par de semanas, para la consultora. Algunas cosas propias, otras que saque de alguna que otra bibliografia interesante.

La evolución al acceso de datos por Microsoft fue desde hace unos años…


Toda esta evolución a acceso a datos, afecto también en la arquitectura de las aplicaciones. Hace tiempo atrás, pensar en una aplicación cliente servidor, en tema datos era una total locura!. Además también se estaba dando a conocer COM (Component Object Model), en el cual al desarrollador le dieron la posibilidad de crear componentes y/o programas reutilizables, permitió usar que un mismo objeto permitiera acceso a datos, sin importar si era una aplicación win32 o ASP, este fue el principio de todo.

Una de las características fundamentales que tenia ADO, es que funcionaba atreves de OLEDB, una api de acceso creada por MS. La ventaja de esto, es que nosotros usábamos los mismos objetos, sin importar la base de datos que estuviese atrás, siempre y cuando esa tuviera un driver de OLEDB. El gran problema de esto, a medida que los motores de base de datos evolucionaron, es que estábamos limitados en aprovechar todo el potencial de la misma, a que no accedíamos a las características principales de los RDBMS.


Cuando llego ado.net no se quiso perder el concepto de “proveedor de datos”. Por este tema los .Net Data Providers, implementan interfaces que definen como deben ser las clases que componen a ado.net, y además posee clases especificas para los RDBMS mas importante del mercado (Oracle y SQL Server).

A la hora de realizar cualquier tipo de conexión en una aplicación de .Net, tendríamos que evaluar nuestro provider, si no usamos ninguno de estos dos motores de base de datos, teníamos que ver si el fabricante, o algún tercero ofrecen un provider para el mismo. Como última elección, pero realmente es la última que se debería tomar, un proveedor de OLEB y ODBC.

Algo a considerar, si trabajos con SQL Server 6.5 o inferior, debemos usar OLEDB, ya que SqlClient no le brinda acceso a esas versiones.

Si accedemos a un Access, como utiliza el JET, tendríamos que caer en OLEDB.

.NET Framework Class Library


Comparto este esquema que vi en una bibliografía…


  • Data Provider For SQL Server: es el proveedor de acceso nativo a servidores de bases de datos Microsoft SQL Server 7.0 o superior, y Microsoft Access. Al conectarse via protocolos nativos de bajo nivel, povee la alternativa más performante para conexiones contra estos motores de bases de datos. Sus clases se encuentran en el namespace System.Data.SqlClient.
  • Data Provider For OLE DB: es el proveedor de acceso a datos que permite interactuar via el protocolo estándar OLE DB con cualquier repositorio de datos que lo soporte. Sus clases se encuentran en el namespace System.Data.OleDb.
  • Data Provider For ODBC: es el proveedor de acceso a datos que permite interactuar via el protocolo estándar ODBC con cualquier repositorio de datos que lo soporte. Sus clases se encuentran en el namespace System.Data.Odbc.
  • Data Porvider For Oracle: es el proveedor de acceso nativo a bases de datos Oracle, desarrollado por Microsoft utilizando las herramientas de conectividad de Oracle. De esta forma puede lograrse un acceso más performante a bases de datos Oracle desde aplicaciones .NET que utilizando ODBC u OLE DB. Sus clases se encuentran en el namespace System.Data.OracleClient, y están compiladas en un assembly diferente al resto: System.Data.OracleClient.dll.

También cabe mencionar que existen muchas clases en ado.net que no pertenecen a ningún provider, ya que son genéricas, por ejemplo el “DataSet”, como también todo lo relacionado con XML.

Entre otras de los cambios que vienen con ADO.net, es modelo de aplicaciones conectadas y desconectadas.

El concepto de aplicación conectada, es sencillo, es lo que la mayoría veníamos haciendo, tener una aplicación que siempre tenia permanentemente contacto con la base de datos.

Esto tiene algunas ventajas y también sus desventajas.

Algunas Ventajas:

  • Al haber una única conexión a la base de datos por usuario, o incluso a veces por aplicación, establecida permanentemente, puede llegar a resultar más sencillo administrar la seguridad y el acceso al servidor de datos. Lo mismo ocurre con el control de concurrencia: en un escenario donde múltiples usuarios se estuvieran conectando y desconectando permanentemente para realizar distintas acciones, este control sería más difícil de llevar.
  • Siempre la aplicación tiene acceso a los datos actualizados

Algunas Desventajas:

  • Se requiere una conexión abierta todo el tiempo con el servidor de base de datos, lo cual consume recursos innecesariamente si no se la está utilizando.
  • La escalabilidad del acceso a los datos se ve limitada por la cantidad de conexiones establecidas simultáneamente contra el servidor de base de datos.

¿Para que querríamos tener una aplicación desconectada? Muy fácil, hay condiciones a veces que el costo de conexión, en tema de velocidad y rendimiento en una aplicación es muy alto, por ejemplo una aplicación win32 que debe consultar un servidor de datos en internet, aunque fuera dentro de una intranet, generaría impacto en la performance del servidor, y en el trafico de la red.

El modelo desconectado, al traer los datos de la base, trabaja con ellos, en la memoria.

Algunas ventajas que provee un escenario de acceso a datos desconectado son:

  • La posibilidad de trabajar sobre los datos independientemente del resto de los usuarios de la aplicación
  • Mayor escalabilidad en el acceso a datos y utlización más óptima de recursos del servidor, ya que se mantiene en un mínimo indispensable la cantidad y duración de conexiones abiertas.
  • Mayor performance, al trabajar con una copia local de los datos.

Algunas Desventajas:

  • Puede ocurrir que en un momento dado un usuario no esté accediendo a los datos más actualizados del repositorio central
  • Al momento de sincronizar los cambios efectuados localmente contra el repositorio central pueden surgir conflictos, los cuales deben ser resueltos manualmente.

Por ejemplo, en el modelo conectado se usa el Data Reader, este hace una lectura secuencial, ósea va registro por registro leyendo. El modelo desconectado esta relacionado con el Data Set, este trae todo en memoria, así que en caso de querer filtrar desde nuestra aplicación los datos, que trajimos de la base de datos, no es necesario volver a pedir esa información, ya que la tememos en el DataSet, ya que este mismo funciona a modo de una tabla virtual en memoria. Permitiendo generar vistas y operaciones sobre la misma, sin impactar en la fuente de datos. Y obviamente posteriormente, podemos sincronizar con la fuente de datos, y bueno.. Este capitulo se ha acabado!

January 11, 2008

Transacciónes – Parte 2

Filed under: ADO.net, ASP.net — José Franco @ 11:43 pm

Hay distinto tipos de Aislamientos en las Transacciones

Se puede ajustar el nivel de aislamiento entre las transacciones y determina para una transacción el grado de aceptación de datos inconsistentes. A mayor grado de aislamiento, mayor precisión, pero a costa de menor concurrencia.

El nivel de aislamiento para una sesión SQL establece el comportamiento de los bloqueos para las instrucciones SQL.

Niveles de aislamiento (Isolation Level):

• ReadUncommited (Lectura no commiteada). Menor nivel. Asegura que no se lean datos corruptos físicamente.
• ReadCommitted (Lectura commiteada). Sólo se permiten lecturas de datos comprometidos.
• RepeatableRead (Lectura repetible). Las lecturas repetidas de la misma fila para la misma transacción dan los mismos resultados.
• Serializable. Mayor nivel de aislamiento. Las transacciones se aíslan completamente.

Comportamiento concurrente de las transacciones.
• Dirty Reads (Lectura sucia). Lectura de datos no comprometidos. (Retrocesos)
• Non-repeatable reads (Lectura no repetible). Se obtienen resultados inconsistentes en lecturas repetidas.
• Phantom reads (Lectura fantasma). Una lectura de una fila que no existía cuando se inició la transacción.

Las transacciones tambien las podemos hacer a Nivel Datos (Data Tier)

DECLARE @TranName VARCHAR(20)
 SELECT @TranName = 'MyTransaction'
 BEGIN TRANSACTION @TranName
 GO
 USE pubs
 GO
 UPDATE roysched
 SET royalty = royalty * 1.10
 WHERE title_id LIKE 'Pc%'
 GO
 COMMIT TRANSACTION MyTransaction
 GO

Y en caso de ocurrir algo, y querer hacer un rollback solo es necesario un “ROLLBACK TRANSACTION”

Bueno ahora vemos el caso de una Transaccion Distribuida



Vamos a reciclar el codigo que usamos para el ejemplo anterior, con el uso de TransactionScope nos quedaria de la siguiente manera

string _ConnectionString = ConfigurationManager.ConnectionStrings[“MyConnectionString”].ConnectionString;
bool _Sucess = false;
string _SqlQuery1 = “UPDATE Products SET Discontinued = 1 where ProductID = 10″;
string _SqlQuery2 = “DELETE OrderDetails where ProductID = 10″;
using (TransactionScope scope = new
TransactionScope(TransactionScopeOption.Required)) {
using (SqlConnection cmd = new
SqlConnection(_ConnectionString))
{
cmd.Open();
using (SqlCommand _command = new
SqlCommand(_SqlQuery1, cmd))
{
int rowsUpdate1 = _command.ExecuteNonQuery();
if (rowsUpdate1 > 0)
{
using (SqlCommand _command2 = new
SqlCommand(_SqlQuery2, cmd))
{
int rowsUpdate2 = _command2.ExecuteNonQuery();
if (rowsUpdate2 > 0)
{
scope.Complete();
_Sucess = true;
}
}
}
}
if (_Sucess)
{
Console.WriteLine(“Se hizo Commit”);
}
else
{
Console.WriteLine(“Se hizo Rollback”);
}
Console.ReadLine();
if (cmd != null)
cmd.Close();
}

Como notaran, ahora en el xxxCommand, no hacemos referencia a ninguna transaccion, cuando usamos en TransactionScope se da a entender que todo el contexto que using es el Scope, antes usabamos el _Success para hacer commit o rollback, ya no es necesario, al hacer el scope.Complete()significa que fue finalizado con éxito.

Si desea deshacer una transacción, no debe llamar al método Complete dentro del ámbito de transacción. Por ejemplo, puede iniciar una excepción en el ámbito. La transacción en la que éste participa se deshará.

El ámbito de transacción se puede anidar llamando a un método que utilice un TransactionScope de otro método que utilice su propio ámbito, como es el caso del método RootMethod en el ejemplo siguiente.

void RootMethod()
 {
 using(TransactionScope scope = new TransactionScope())
      {
           /* Perform transactional work here */
           SomeMethod();
           scope.Complete();
      }
 }
 void SomeMethod()
 {
  using(TransactionScope scope = new TransactionScope())
      {
           /* Perform transactional work here */
           scope.Complete();
      }
 }

La clase TransactionScope proporciona varios constructores sobrecargados que aceptan una enumeración del tipo TransactionScopeOption, que define el comportamiento transaccional del ámbito.

Un objeto TransactionScope tiene tres opciones:

  • Unirse a la transacción de ambiente o crear una nueva si no existe ninguna.
  • Convertirse en un nuevo ámbito raíz, es decir, iniciar una nueva transacción que sea la nueva transacción de ambiente dentro de su propio ámbito.
  • No participar en una transacción. Por lo tanto, no existirá ninguna transacción de ambiente.

Si se crea una instancia del ámbito con Required, y hay presente una transacción de ambiente, el ámbito se une a esa transacción. Si, en cambio, no existe ninguna transacción de ambiente, el ámbito crea una nueva transacción y se convierte en el ámbito raíz. Éste es el valor predeterminado. Cuando se utiliza Required, el código del ámbito no tiene que comportarse de forma distinta en función de si es el ámbito raíz o si simplemente se une a la transacción de ambiente. Debe comportarse de la misma manera en ambos casos.

Si se crea una instancia del ámbito con RequiresNew, éste se convierte siempre en el ámbito raíz. Inicia una nueva transacción y su transacción se convierte en la nueva transacción de ambiente dentro del ámbito.

Si se crea una instancia del ámbito con Supress, éste nunca participa en una transacción, independientemente de si hay una transacción de ambiente presente. Para un ámbito del que se haya creado una instancia y que tenga este valor, null es siempre su transacción de ambiente.

TransactionScopeOption  Transacción de ambiente  El ámbito participa en 
Requerida (Required)  No  Nueva transacción (será la raíz) 
Se requiere nueva (RequiresNew) No  Nueva transacción (será la raíz) 
Suprimir (Suppress)  No  Sin transacción 
Requerida (Required)    Transacción de ambiente 
Se requiere nueva (RequiresNew)    Nueva transacción (será la raíz) 
Suprimir (Suppress)    Sin transacción
using(TransactionScope scope1 = new TransactionScope())
{
try { //Start of non-transactional section  using(TransactionScope scope2 = new
TransactionScope(TransactionScopeOption.Suppress)) { //Do non-transactional work here }
  //Restores ambient transaction here }
 catch {}
 //Rest of scope1 }

Y Si quisieramos obtener referencia sobre la transaccion actual, tendriamos que hacer lo siguiente

System.Transactions.Transaction Current = System.Transactions.Transaction.Current;
System.Transactions.TransactionInformation info = Current.TransactionInformation;
Console.WriteLine(“Isolation level: {0}”, Current.IsolationLevel.ToString());
Console.WriteLine(“Creation time: {0}”, info.CreationTime);
Console.WriteLine(“Status: {0}”, info.Status);
Console.WriteLine(“Local ID: {0}”, info.LocalIdentifier);
Console.WriteLine(“Distributed Id: {0}”, info.DistributedIdentifier);

Nuestra salida seria

Referencia:

January 9, 2008

Transacciónes – Parte 1

Filed under: ADO.net, ASP.net — Tags: — José Franco @ 7:20 pm

Las transacciones son grupos de comandos de base de datos que se ejecutan como un paquete. Al utilizar una transacción, su aplicación tiene la posibilidad de anular (deshacer) todos los cambios ejecutados desde la misma si se producen errores durante alguna parte del proceso de transacción. Por ejemplo, consideremos que una aplicación tiene dos tablas, una de las cuales representa el inventario y la otra los pedidos. Cuando se agrega un pedido a una tabla, es necesario reducir el inventario correspondiente en la otra tabla. Si se realizase una actualización de la tabla Orders correctamente pero se produjese un error al actualizar la tabla Inventory, se pondría en peligro la integridad de los datos. Para garantizar que ambas tablas se actualicen correctamente, podría empaquetar los dos comandos de datos en una sola transacción. Si una tabla se actualiza correctamente pero la otra tabla no, se puede deshacer la transacción completa, resolver los problemas que provocaron el error y volver a intentar la transacción.

Es importante considerar a la hora de evaluar de implementar una Transacccion es que el el origen de datos debe admitir transacciones.

Para garantizar un comportamiento predecible, todas las transacciones deben poseer las propiedades ACID básicas (atómica, coherente, aislada y duradera). Estas propiedades refuerzan la función de las transacciones críticas, así como las proposiciones todo o nada. En resumen, ACID garantiza que un conjunto de tareas relacionadas se ejecuten correctamente o presenten problemas como unidad. En términos de procesamiento, las transacciones se confirman o se anulan. Para que una transacción se confirme, todos los participantes deben garantizar la permanencia de los cambios efectuados en los datos. Los cambios deben conservarse aunque el sistema se bloquee o tengan lugar otros eventos imprevistos. Basta con que un solo participante no pueda garantizar este punto para que la transacción no funcione en su totalidad. Todos los cambios efectuados en datos dentro del ámbito de la transacción se deshacen hasta un punto específico establecido.

El .NET Framework provee suporte para transacciones locales y distribuidas.

  • Transacciones Locales(Local transactions). Se podran definir como un cojunto de operaciones que van destinado a una solo data source que puede ser una base de datos, o un Message Queue. Obviamente el datasource tiene que proveeder la capacidad de manejar transacciones locales. Este tipo de transacciones son controladas por el Data Source, y son eficientes y sencillas de manejar.
  • Transacciones Distibuidas (Distributed transactions). Las transacciones de este tipo pueden abarcar varios data sources. Las transacciones distribuidas permiten incorporar en una sola acción de cumplimiento o incumplimiento varias operaciones distintas que tienen lugar en sistemas diferentes. En este caso, las transacciones se coordinan mediante el Coordinador de transacciones distribuidas de Microsoft (MSDTC) que reside en cada sistema, con la Accion Atomic, que tiene como resultado su existo, o fallo total.

Propiedades de una Transaccion (ACID propiedades):

  • Atomic(Atomicidad) Es la propiedad de las transacciones que permite observarlas como operaciones atómicas: ocurren totalmente o no ocurren.Casos a considerar:
    • Consultas unitarias. Incluso para consultas unitarias hay que preservar la atomicidad: en un sistema operativo de tiempo compartido, la ejecución concurrente de dos consultas SQL puede ser incorrecta si no se toman las precauciones adecuadas.
    • Operación abortada. Por ejemplo, debido a una división por cero; por privilegios de acceso; o para evitar bloqueos.

    Las operaciones asociadas a una transacción comparten normalmente un objetivo común y son interdependientes. Si el sistema ejecutase únicamente una parte de las operaciones, podría poner en peligro el objetivo final de la transacción. La atomicidad elimina la posibilidad de procesar un subconjunto de operaciones.

  • Consistent(Consistencia) La ejecución aislada de la transacción conserva la consistencia de la base de datos.La coherencia requiere que los datos enlazados mediante una transacción se mantengan en términos de semántica. Una parte de la responsabilidad para mantener la coherencia recae en el programador de la aplicación que debe asegurarse de que ésta exija todas las restricciones de integridad conocidas. Por ejemplo, en el desarrollo de una aplicación en la que se transfiere dinero, se debe evitar el desplazamiento arbitrario de los puntos decimales durante la transferencia.
  • Isolated(Aislamiento) Una transacción es una unidad de aislamiento, permitiendo que transacciones concurrentes se comporten como si cada una fuera la única transacción que se ejecuta en el sistema.

    El aislamiento requiere que parezca que cada transacción sea la única que manipula el almacén de datos, aunque se puedan estar ejecutando otras transacciones al mismo tiempo. Una transacción nunca debe ver las fases intermedias de otra transacción.

    Para cada par de transacciones que puedan ejecutarse concurrentemente Ti y Tj, se cumple que para los efectos de Ti:

    - Tj ha terminado antes de que comience Ti
    - Tj ha comenzado después de que termine Ti

    Las transacciones son independientes entre sí.

  • Durable(o Permanencia) Una transacción también es una unidad de recuperación. Si una transacción se realiza satisfactoriamente, el sistema garantiza que sus actualizaciones se mantienen aunque el equipo falle inmediatamente después de la confirmación. El registro especializado permite que el procedimiento de reinicio del sistema complete las operaciones no finalizadas, garantizando la permanencia de la transacción.

Bueno vamos a hacer nuestra primer transaccion, los pasos a seguir son:

El framework .Net nos ofrece los siguientes proveedores de Transacciones

Imaginemos que tenemos esta situacion: Necesito poner “Discontinuado” algun producto mio, por Ejemplo el ProductID 10, y luego, borrar todos los registros que esten en el historial de Ordenes.

Nuestro Codigo nos quedaria algo asi:

string _ConnectionString = ConfigurationManager.ConnectionStrings[“MyConnectionString”].ConnectionString;
bool _Sucess = false;
SqlTransaction _Transaction = null;
string _SqlQuery1 = “UPDATE Products SET Discontinued = 1 where ProductID = 10″;
string _SqlQuery2 = “DELETE OrderDetails where ProductID = 10″;
using (SqlConnection cmd = new
SqlConnection(_ConnectionString))
{
try
{
cmd.Open();
_Transaction= cmd.BeginTransaction();
using (SqlCommand _command = new
SqlCommand(_SqlQuery1, cmd, _Transaction))
{
int rowsUpdate1 = _command.ExecuteNonQuery();
if (rowsUpdate1 > 0)
{
using (SqlCommand _command2 = new
SqlCommand(_SqlQuery2, cmd, _Transaction))
{
int rowsUpdate2 = _command2.ExecuteNonQuery();
if (rowsUpdate2 > 0)
{
_Sucess = true;
}
}
}
}
}
finally
{
if (_Sucess)
{
_Transaction.Commit();
Console.WriteLine(“Se hizo Commit”);
}
else
{
_Transaction.Rollback();
Console.WriteLine(“Se hizo Rollback”);
}
Console.ReadLine();
if (cmd != null)
cmd.Close();
}

Si presta atencion:

int rowsUpdate2 = _command2.ExecuteNonQuery();
if (rowsUpdate2 > 0){
_Sucess = true;
}

Solo nos esta dando como valida la transaccion si borra algun registro, en el historial, sino lo da como erroneo.

Bueno, justamente en una transaccion tenemos que evaluar todos estos detalles, sino hace un rollback, y no se realiza ningun cambio.
Algo para señar es el tema de try y finally, esta pensado asi, en caso de que salte alguna excepcion, imaginen que estan haciendo una transaccion, y una de las querys, o por falta de permisos no podemos ver una tabla, va a saltar una excepcion, pero los pasos anteriores se concretaron, al no hacer el rollback , vamos a tener problemas de integridad de datos.

Tambien podriamos haber definido el nivel de aislamiento

_Transaction= cmd.BeginTransaction(IsolationLevel.Serializable);

Powered by WordPress