Ir al contenido principal

VB XML Literals

Desde la versión 9.0 de VB .Net existe una característica llamada XML Literals la cual consiste en poder escribir XML directamente en el código VB y manejar el xml como parte del lenguaje.

Actualmente cuando en una solución necesito trabajar con XML, donde generalmente hay puros proyectos de C#, también agrego un proyecto en VB.Net solo para el manejo de XML por que se me facilita con XML Literals.

Para mostrar como se utiliza XML Literals mostraré un ejemplo (el clásico ejemplo de una orden) el cual consiste en una clase que exporta e importa ordenes a/desde XML.

Para esto creo una solución con 3 proyectos uno de tipo C# Windows library con el nombre XmlLiteralsExample.Domain el cual contiene las clases Order y OrderItem con esta definición

namespace XmlLiteralsExample.Domain
{
public class Order
{
public int Id { get; set; }
public string Customer { get; set; }
public List<OrderItem> Items { get; set; }

public Order()
{
Items = new List<OrderItem>();
}
}

public class OrderItem
{
public int ProductId { get; set; }
public int Quantity { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
}
}

Ahora agrego el proyecto de tipo VB Class library llamado XmlLiteralsExample.Tasks en el cual agregaré la clase en VB que me ayudará con el XML

Imports XmlLiteralsExample.Domain

Public Class OrderXmlTasks
Public Function ReadFromFile(ByVal FileName As String) As Order
Throw New NotImplementedException()
End Function

Public Sub
SaveToFile(ByVal FileName As String)
Throw New NotImplementedException()
End Sub

Public Function
FindOrderItem(ByVal FileName As String, _
ByVal ProductId As Integer) As OrderItem

Throw New NotImplementedException()
End Function

End Class

XmlLiteralsSolution Y por último agrego un proyecto para las pruebas unitarias en C# llamado XmlLiteralsExample.Tasks.Test en el cual agregaré las pruebas unitarias para nuestra clase OrderXmlTasks y un archivo xml para las pruebas.

El proyecto XmlLiteralsExample.Test tiene referencias al proyecto Domain así como el proyecto XmlLiteralsExample.Tasks.Test tiene referencias a los otros 2 proyectos de la solución

Además el proyecto de prueba incluye una referencia a las extensiones SharpTestsEx

El Archivo Order.xml contiene una orden de prueba

<?xml version="1.0" encoding="utf-8" ?>
<
order id="123" xmlns="urn:schemas-developeando-com:xmlLiterals">
<
customer>Homer Simpson</customer>
<
items>
<
item productID="1" quantity="2" price="1.50">product desc 1</item>
<
item productID="2" quantity="4" price="2.60">product desc 2</item>
<
item productID="3" quantity="6" price="3.80">product desc 3</item>
</
items>
</
order>

A partir del archivo de prueba (Order.xml) genero el xml schema utilizando la opción del menú XML de VisualStudio y la guardo en el folder del proyecto Tasks y después agrego el archivo al proyecto. Con esto puedo importar el xml namespace en el archivo OrderXmlTasks.vb como si fuera un namespace de .net

Imports <xmlns="urn:schemas-developeando-com:xmlLiterals">

Esto me ayudará a que visual studio conozca la estructura de mi xml y así pueda darme opciones a través de intellisense

Ahora que tengo los datos de prueba iniciamos con con la funcionalidad, para ello escribo mi primer test en la clase OrderXmlTasksTest (dentro del proyecto de prueba)

[TestMethod]
public void should_load_order_from_file()
{
var orderXmlTasks = new OrderXmlTasks();
var order = orderXmlTasks.ReadFromFile(@"C:\..\..\Order.xml");

order.Id.Should().Be.EqualTo(123);
order.Customer.Should().Be.EqualTo("Homer Simpson");
order.Items.Count.Should().Be.EqualTo(3);
}

Ahora el código para pasar esta prueba:

Public Function ReadFromFile(ByVal FileName As String) As Order
Dim orderXml = XElement.Load(FileName)

Dim order = New Order()
With order
.Id = orderXml.@id
.Customer = orderXml.<customer>.Value
End With

For Each
itemXml In orderXml.<items>.<item>
Dim item = New OrderItem()
With item
.ProductId = itemXml.@productID
.Quantity = itemXml.@quantity
.Price = itemXml.@price
.Description = itemXml.Value
End With
order.Items.Add(item)
Next

Return
order
End Function

Ahora explico un poco lo que hace el código; la primer línea carga el xml a un objeto. En este ejemplo uso la clase XElement la cual carga el xml a partir del elemento raíz (en este caso la etiqueta Order). Por lo tanto el objeto orderXml me representa la etiqueta Order del archivo xml. Después creo un objeto order que después lleno con los datos del archivo xml cargados en el objeto orderXml.

En XML Literals para accesar a los atributos de un elemento xml utilizamos la @ es por eso que podemos ver que de carga en la propiedad Id, del objeto order, el valor del atributo id del elemento order del xml. Después se puede notar que para tener acceso a los elementos hijos solo hace falta escribir las etiquetas tal y como lo haríamos en un archivo xml y gracias a que importe el namespace xml también tengo intellisense

intellisense

de igual forma en una ciclo for each acceso a la colección de items. En este caso acceso al elemento item a través de toda la ruta de elementos hijos.

intellisense2

Pero además XML literals me permite accesar a elementos hijos sin tener que seguir la ruta usando tres puntos entre el objeto y la etiqueta.

Para obtener al texto dentro de una etiqueta se utiliza la propiedad Value del objeto XElement. Así es como obtengo el nombre del cliente y la descripción de los ítems.

Bueno este post ya se extendió y tengo que dividirlo, seguiré con el ejemplo en otro post.

Comentarios

Entradas más populares de este blog

Bloqueos

Una de las preguntas típicas de las juntas matutinas en los equipos de desarrollo de software es ¿Hay algún bloqueo? Si lo hay, se trata de ver qué es lo que está esperando esa persona y encontrar la forma de que se desbloquee; pero ¿Qué son los bloqueos? Los bloqueos son obstáculos que te impiden realizar o avanzar en tu trabajo. Evitan que puedas seguir progresando en el proyecto.

He notado que es común en las personas con menos experiencia decir que tienen un bloqueo cuando están batallando, debido a su poca experiencia, en la forma de resolver un problema. Han intentado varias formas y se empiezan a quedar sin ideas de como puede ser resuelto el problema o como pueden cumplir con el requerimiento especificado. Al quedarse sin opciones de qué intentar dicen que tienen un bloqueo con la tarea y que a menos que alguien les diga como resolverlo, no se puede avanzar en la tarea.

En personas con más experiencia, ese tipo de bloqueos no ocurren, una persona con experiencia ha visto pro…

Firebird 2.1 UPDATE OR INSERT

Another great feature that I like in Firebird 2.1 is the UPDATE OR INSERT statement. It's a really time saver and it makes the SQL cleaner.

For example suppose I have a products table like the one I use in my last post and an inventory table to store the product stock. Before Firebird 2.1 if I want to set the stock for a product I needed to check if a record for that product_id already exists; if the product_id already exists then I write an update. If not then I write an insert statement. So I ended up with something like this:


IF EXISTS(SELECT * FROM inventory WHERE product_id = :product_id ) THEN
UPDATE
inventory
SET
stock = :stock
WHERE
product_id = :product_id;
ELSE
INSERT INTO inventory
(product_id, stock)
VALUES
(:product_id, :stock);

In this example I only update one field but when I have to update a big table I ended up with a big chunk of code and thinking: "there should be another (better) way to do this".

Fortunately now with Firebird 2.1 there…

Database Mail en MS SQL Server 2005

Configuración de Database Mail en MS SQL Server 2005

Primero se debe de habilitar, ya que por omisión el componente esta deshabilitado, Utilizando el SSMS (SQL Server Management Studio)


Si no esta habilitado aparecerá un mensaje preguntado si lo habilita, después aparece esta ventana donde se pregunta al usuario que es lo desea hacer.


Seleccionamos la primera opción para crear un perfil.


Configuramos el perfil y le agregamos por lo menos una cuenta.


Seleccionamos el perfil como public y default.


Para mandar correo se utiliza el procedimiento msdb.sp_send_dbmail por lo tanto el usuario que intente mandar correo debe de tener permiso para la base de datos msdb.

Referencias:
http://www.sqlservercentral.com/columnists/cBunch/introtodatabasemailinsql2005.asp