November 2009 - Artículos

El uso de Contains en LINQ - IN or NOT IN en SQL

Hay veces en las que desarrollando una aplicación Software, nos interesa obtener los elementos de una colección que contienen o que no contienen un conjunto de elementos.

Para ello, en LINQ hacemos uso de la extensión Contains.
De cara a SQL, esto sería similar a la instrucción que ejecutamos con la palabra IN.

SELECT * FROM Tabla WHERE campo NOT IN ('', '', ...)

La mejor forma de entender bien el funcionamiento de Contains, es verlo con un ejemplo.

El siguiente ejemplo es únicamente demostrativo y esta escrito en C#.

Comenzamos por crear una clase muy simple de productos frutales por decir algo:

public class Product
{
    
public string fruit { getset; }
}

Y finaliza con el código de ejemplo demostrativo de LINQ y Contains:

string[] fruits = new string[] { "Peras""Platanos" };
List<Product> productsCollection = new List<Product>();
productsCollection.Add(
new Product() { fruit = "Naranjas" });
productsCollection.Add(
new Product() { fruit = "Peras" });
productsCollection.Add(
new Product() { fruit = "Limones" });
productsCollection.Add(
new Product() { fruit = "Platanos" });
var productElements = from element in productsCollection
                      
where !(fruits.Contains(element.fruit.ToString()))
                      
select element;
productsCollection = productElements.ToList();
foreach (var item in productsCollection)
{
    
MessageBox.Show(item.fruit);
}            

Como podemos ver en este ejemplo, creamos una colección de frutas y una matriz con el nombre de dos frutas.
Lo que queremos obtener son todas las frutas que no estan contenidas en la matriz.
Es decir, todas las frutas que no son ni Peras ni Platanos.
En SQL estándar serían las frutas NOT IN ('Peras', 'Platanos').

Adicionalmente, también podemos hacer uso de las funciones Lambda, por lo que todo el funcionamiento anterior, se resumiría de la siguiente manera (equivalente de la anterior):

string[] fruits = new string[] { "Peras""Platanos" };
List<Product> productsCollection = new List<Product> { 
                                   
new Product { fruit="Naranjas" }, 
                                   
new Product { fruit="Peras" }, 
                                   
new Product { fruit="Limones" }, 
                                   
new Product { fruit="Platanos" }
                                   };
productsCollection = 
productsCollection.Where((n) => !(fruits.Contains(n.fruit.ToString()))).ToList();
foreach (var item in productsCollection)
{
    
MessageBox.Show(item.fruit);
}

Espero que quede clara (para quien lo necesite) la funcionalidad, beneficios y usos de Contains en LINQ.

Cross Posted from Jorge Serrano - MVP Visual Developer - VB

¿Cómo usar Caching en una aplicación Windows (WPF o WinForms)?

Visual Studio 2010 introduce muchas mejoras e interesantes características algunas de las cuales son extensiones de un "mundo" hacia el "otro", y en el caso concreto de esta entrada, el uso de Caching que se hacía en Web a Windows, en aplicaciones de escritorio, con WPF o WinForms.

Hay momentos en el desarrollo Web, que nos interesa mantener datos o informaciones en caché, que por motivos determinados no nos interesa estar consultando constantemente.
Esa posibilidad se materializa en el ambiente Web gracias al objeto System.Web.Caching.Cache [http://msdn.microsoft.com/es-es/library/system.web.caching.cache.aspx].

El caso es que el trabajo con datos cacheados se hizo tan popular y necesario, que muchas aplicaciones Windows utilizan esta librería.
El problema es que se producía un mal uso del ensamblado System.Web.dll que debíamos referenciar para poder usar el objeto caché de ASP.NET, pero como digo, en un ambiente Windows, anti-natural si se me permite la expresión con el propósito del ensamblado que estaba diseñado para ser utilizado en un ambiente Web.

Funcionar funcionaba, ahora bien, no es la mejor práctica sin lugar a dudas, y muchas aplicaciones de escritorio la utilizan.

Por esa razón, la gente de Microsoft empezó a pensar en cómo crear objetos que permitieran de forma más liviana, ofrecer los mecanismos de cacheo que posee las aplicaciones Web en un ambiente Windows utilizando sus ensamblados.

Así, surgió el ensamblado System.Runtime.Caching.dll que es propio de .NET Framework 4.0 y que contiene dos clases principales.
La primera de esas clases tiene como misión abstraer los tipos con el fin de implementar tipos personalizados de caché.
La segunda de esas clases implementa en memoria un objeto de caché concreto a través de la clase System.Runtime.Caching.MemoryCache.

Quizás, la mejor forma de ver esto es haciendo un ejemplo práctico que nos muestre como trabajar con datos cacheados en una aplicación Windows, y así comprenderemos mucho mejor todo esto.

Iniciaremos una nueva aplicación Windows en C# con Visual Studio 2010 y agregaremos a la ventana tres controles Button y dos controles Label, tal y como se muestra a continuación:

 

Dentro de nuestra aplicación, deberemos realizar diferentes acciones.

Por un lado, agregaremos una referencia al ensamblado System.Runtime.Caching.dll.
Este ensamblado no se encuentra en la ventana de referencias de .NET, sino que deberemos ir a la ruta [C:\WINDOWS\Microsoft.NET\Framework\v4.0.21006\System.Runtime.Caching.dll] para seleccionarlo.

Una vez seleccionado, observaremos que el ensamblado aparece en las referencias con un icono de aviso.
Esto es debido a que la aplicación Windows por defecto, está como Microsoft .NET Framework 4 Client Profile, por lo que el ensamblado indicado no forma parte del paquete distribuible Clien Profile (para más información, ver la entrada anterior que escribí en mi blog sobre esto) y de ahí que salga el aviso en las referencias del proyecto.
Haremos clic con el botón derecho del ratón sobre el proyecto y seleccionaremos la opción Propiedades.
En las propiedades del proyecto, seleccionaremos como Target framework a ".NET Framework 4".

Una vez hecho esto, Visual Studio 2010 nos avisará de que estamos cambiando la opción de distribución.
Indicaremos que sí, y seguiremos adelante.
Lo primero es que el ensamblado que aparecía con un icono de advertencia, ha desaparecido y podemos importar el namespace al proyecto y trabajar con sus clases y miembros.

Una vez que hemos llegado a este punto, nos focalizamos ya en el código de nuestra aplicación.

La primera acción será la de agregar nuestro namespace a la cabecera de la clase del formulario a través de la siguiente instrucción:

using System.Runtime.Caching;

Finalmente, nos centraremos en el resto del código de nuestro ejemplo que es el que se indica a continuación:

/// <summary>
/// Cargamos el formulario.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Load(object sender, EventArgs e)
{
    
// Inicializamos los controles Label a blanco.
    
this.label1.Text = "";
    
this.label2.Text = "";
// Form1_Load


/// <summary>
/// Creamos un objeto ObjectCache, y 
/// referenciamos a MemoryCache.
/// </summary>
private ObjectCache cacheName = MemoryCache.Default;


/// <summary>
/// Metodo para cargar los datos de cache de ejemplo.
/// </summary>
private void LoadCacheData()
{
    
// Mostramos el mensaje que indica que se estn cargando los datos de la cache.
    
this.label2.Text = "Cargamos los datos a la cache";
    
// Declaramos un objeto para las politicas.
    
CacheItemPolicy policy = new CacheItemPolicy();
    
// Indicamos la prioridad de la politica.
    policy.Priority = 
CacheItemPriority.Default;
    
// Preparamos un contenido para guardar en la cache.
    
string name = "Antonio " + DateTime.Now.ToString();
    
// Almacenamos el contenido anterior en la cache.
    cacheName.Set(
"name", name, policy);
// LoadCacheData


/// <summary>
/// Cargamos y mostramos los datos de cache.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
    
// Obtenemos los datos de la cache.
    
string name = cacheName["name"as string;
    
// Si lo que obtenemos es nulo, es porque 
    
// no hay datos cargamos en la cache.
    
if (name == null)
    {
        
// No hay dados en la cache... => cargarmos los datos.
        LoadCacheData();
    }
    
// Mostramos el mensaje que indica que se muestran los datos de la cache.
    
this.label1.Text = "Mostramos los datos de la cache :: " + cacheName["name"].ToString();
// button1_Click


/// <summary>
/// Eliminamos la cache.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button2_Click(object sender, EventArgs e)
{
    
// Eliminamos los datos de la cache.
    cacheName.Remove(
"name"null);
    
// Mostramos el mensaje que indica que se 
    
// han eliminado los datos de la cache.
    
this.label1.Text = "Eliminamos los datos de la cache";
    
this.label2.Text = "";
// button2_Click


/// <summary>
/// Modificamos los valores de la cache.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button3_Click(object sender, EventArgs e)
{
    
// Preparamos un nuevo contenido para la cache.
    
string name = "Luis " + DateTime.Now.ToString();
    
// Preparamos una nueva politica para los datos de la cache.
    
CacheItemPolicy policy = new CacheItemPolicy();
    
// Establecemos la prioridad de la politica.
    policy.Priority = 
CacheItemPriority.Default;
    
// Indicamos una expiracion de 5 segundos.
    policy.AbsoluteExpiration = 
DateTimeOffset.Now.AddSeconds(5);
    
// Establecemos los valores nuevos de la cache con su politica nueva.
    
// La expiracion sera de 5 segundos.
    
// Pasados esos 5 segundos, el contenido de la cache se borrara.
    cacheName.Set(
"name", name, policy);
    
// Mostramos el mensaje que indica que los
    
// datos de la cache se han eliminado.
    
this.label1.Text = "Modificamos los datos de la cache (5 segundos para consultar)";
    
this.label2.Text = "";
// button3_Click

Este ejemplo tiene como misión crear datos en la caché si no existen (primer botón), eliminar los datos de la caché (segundo botón), modificar/crear datos en la caché con una expiración de 5 segundos (tercer botón), pasados los cuales, los datos de la caché se eliminarán automáticamente. Si jugamos con estas tres opciones, comprenderemos mejor aún el comportamiento y funcionamiento de Caching.

Como podemos observar, el funcionamiento de System.Runtime.Caching es muy similar al Caching de System.Web, eso es así porque la gente de Microsoft ha querido hacer esto de forma que la gente que está familiarizada con el Caching de Web, no encuentre muchos cambios con respecto al nuevo ensamblado de Caching que ha creado Microsoft.

Cross Posted from Jorge Serrano - MVP Visual Developer - VB

¿Qué es Client Profile en Visual Studio 2010?

Continúo comentando alguna de las incorporaciones de Visual Studio 2010, y en concreto, una que tiene por nombre Client Profile, si bien, Client Profile se deja ver ya en .NET Framework 3.5 SP1, es en .NET Framework 4.0 cuando adquiere más importancia.

En Microsoft han pensado que la distribución de aplicaciones WPF y aplicaciones de Windows, se hace a veces excesivamente pesada a costa de distribuir el Framework de .NET.

Ese Framework se ha hecho bastante pesado y a veces para usar solo una parte.

Es por todo ello, que Microsoft ha decidido crear dos paquetes... bueno... uno nuevo solamente en realidad.
Uno de esos paquetes es el paquete de distribución tradicional, el que denominan .NET Framework 4.0 ó .NET Framework 4.0 full y que todos conocemos muy bien.
El otro y nuevo, es el .NET Framework 4.0 Client Profile.

Este paquete, .NET Framework 4.0 Client Profile, contiene únicamente una parte de librerías del Framework, aquellas que Microsoft ha estimado como las más usadas o más comunes para las aplicaciones de escritorio WPF y Windows.

Los paquetes Client Profile en .NET Framework 4.0 están disponibles tanto para sistemas de 32 bits como para sistemas de 64 bits, a excepción del procesador IA64.

Respecto a los tamaños del Client Profile, éstos se han reducido drásticamente desde la Beta 1 a la Beta 2.
Para un entorno de 32 bits por ejemplo, el tamaño ha pasado de 34 Mb a 31 Mb, y para ambos entornos, 32 bits y 64 bits, ha pasado de 71 Mb a 47 Mb.

Desde mi punto de vista, ésto del Client Profile no me termina de convencer del todo, pero entiendo que la gente de Microsoft lo habrá hecho por alguna razón o interés general, así que de momento me quedo a la espectativa.

Finalmente, debo indicar que dentro del entorno de desarrollo, haciendo clic con el botón derecho del ratón sobre el proyecto y seleccionando la opción Propiedades del menú emergente, accederemos a las propiedades del proyecto, dentro de las cuales encontraremos la parte definida como Target framework dento de la cual, podremos seleccionar el tipo de compilación que queremos realizar, con Client Profile (por defecto para una aplicación WPF y Windows), o con el framework completo.

También podemos acceder a esta opción desde las opciones avanzadas del compilador.

Para terminar, querría dejar dos enlaces con información de Client Profile para la Beta 1 [http://blogs.msdn.com/jgoldb/archive/2009/05/27/net-framework-4-client-profile-introduction.aspx] y para la Beta 2 [http://blogs.msdn.com/jgoldb/archive/2009/10/19/what-s-new-in-net-framework-4-client-profile-beta-2.aspx], sacadas de un blog de Microsoft. En el segundo de los enlaces, encontraremos cuadros comparativos bastante descriptivos así como informaciones de utilidad y qué partes del Framework se incluyen en el Client Profile.

Cross Posted from Jorge Serrano - MVP Visual Developer - VB

El nuevo método IsNullOrWhiteSpace de Visual Studio 2010

Nota previa: Aunque la siguiente entrada tiene su foco puesto en VB como lenguaje, es igualmente aplicable a C#.

Dentro de nuestras aplicaciones nos encontramos con situaciones en las que tenemos que evaluar si una cadena de texto tiene información o no.

Podemos preguntar si una cadena es nula o está vacía de la forma siguiente:

Dim test As String
If
 (test Is Nothing Or
    test = ""Then
    MessageBox.Show("nulo o vacio")
End If

La ejecución de estas instrucciones en Visual Basic 2010 nos mostrará un mensaje en pantalla con el mensaje de nulo o vacío.

Si cambiamos las líneas anteriores por estas otras donde el único cambio es la asignación de una cadena vacía en la variable test:

Dim test As String = "" 
If
 (test Is Nothing Or
    test = ""Then
    MessageBox.Show("nulo o vacio")
End If

Seguimos obteniendo el mismo resultado.

Ahora bien, Visual Studio nos proporciona un método que simplifica bastante la pregunta acerca de una cadena, si es nula o vacía.

Ese método es el método IsNullOrEmpty.

El código anterior quedaría entonces enormemente simplificado de la siguiente manera:

Dim test As String
If
 (String.IsNullOrEmpty(test)) Then
    MessageBox.Show("nulo o vacio")
End If

Sin embargo, si modificamos el código por este otro:

Dim test As String = " "
If (String.IsNullOrEmpty(test)) Then
    MessageBox.Show("nulo o vacio")
End If

Observaremos que ahora el método IsNullOrEmpty no detecta que la cadena es una cadena vacía, ya que el espacio en blanco hace que no sea vacía.

Sin embargo, la diferencia entre el espacio en blanco y una cadena vacía es a veces discutible y muy estrecha.

Para algunos, un espacio en blanco representa un caracter (el 32 para más señas), sin embargo, para otros... ese espacio en blanco no contiene información relevante en según que procesos y les gustaría que fuera detectado como cadena vacía. ¿Quién tiene la razón?.

Por esto y para resolver el problema, aparece en escena el método IsNullOrWhiteSpace que ha sido incluido en .NET Framework 4.0 y por ende en Visual Studio 2010, el cual nos indica si una cadena es nula o vacía, entendiendo por vacía el espacio o espacios en blanco.

El ejemplo anterior último para quien quiera tratar el carácter 32 (espacio en blanco) como cadena vacía, quedaría representado de la siguiente manera:

Dim test As String = " "
If (String.IsNullOrWhiteSpace(test)) Then
    MessageBox.Show("nulo o vacio")
End If

En esta oportunidad, nuestra cadena con un espacio en blanco, será interpretada como cadena vacía, o mejor dicho, se entenderá que no hay caracteres representativos entiendo como único caracter no representativo el caracter 32.

En mi caso, antes de este método tenía implementada una función extensible que hacía esta acción. Ahora, esa función extensible pasará a mejor vida gracias a este nuevo método de Visual Studio 2010.

Cross Posted from Jorge Serrano - MVP Visual Developer - VB

Microsoft Visio 2010 Beta pública en breve

No sé vosotros, pero yo uso Visio en muchísimas ocasiones para preparar documentos de requerimientos, diseños técnicos, documentos de pruebas, manuales, artículos en revistas, etc.

Como usuario de Visio, me gusta y mucho ver qué características trae las nuevas versiones de Visio.

El caso de esta entrada no es contar qué cosas nuevas trae o traerá Visio 2010, sino ofrecer la posibilidad de acceder a la versión Beta pública de Visio 2010 que aparecerá en las próximas semanas.

La gente de Microsoft ha creado un nuevo sitio [http://visiotoolbox.com/2010/] a través del cual escribir un mensaje de correo electrónico para que nos notifiquen automáticamente cuando aparece la versión de prueba para tener acceso a ella.

En esa web encontraremos detalles e información sobre la nueva versión de Visio.

La Web por otro lado, tiene aspecto Visio como no podía ser de otra forma. :-)

Espero que sea del agrado de más de uno.

Cross Posted from Jorge Serrano - MVP Visual Developer - VB
Posted por Jorge Serrano con no comments
Archivado en: