miércoles, 12 de noviembre de 2014

Visual Studio 2013 Community Edition

Visual Studio Community Edition
Microsoft acaba de sacar hoy una nueva versión de Visual Studio 2013 totalmente gratuita, que elimina las limitaciones que teníamos con las versiones Express, pudiendo instalar extensiones y eliminando la barrera que había anteriormente en la versión Express con versiones Web y Desktop.

Esta versión es gratuita para profesionales, estudiantes y pequeños equipos hasta 5 programadores.

Más información y descarga en http://www.visualstudio.com/news/vs2013-community-vs

ASP.NET 5 multiplataforma
ASP.Net 5 estará disponible para Windows, Mac y Linux. Incluirán un web server propio.


Otras novedades
- El .NET core Framework pasa a ser OpenSource
- Se prepara un CLR de .NET para Mac y para Linux, por lo que se podrá programar con .NET en estas plataformas

Tenéis más información en el blog de Scott Hanselman.


La verdad es que son muy buenaa noticia para los desarrolladores de .NET.







lunes, 11 de agosto de 2014

Dapper, un micro ORM a tener en cuenta

Los ORM (Mapeo objeto – relacional) son una pieza fundamental en el desarrollo de nuestras aplicaciones.
Permite interactuar con la base de datos mediante objetos y listas de objetos, olvidándonos de los tediosos datasets.

Cuando hablamos de ORM nos viene a la cabeza Entity Framework y Nhibernate, pero existen también los llamados micro-orm que son bastante más ligeros y, siendo más simples que los ORM convencionales,  cumplen su función banstante bien, como pueden ser, entre otros, Massive, Simple.Data, Peta Poco y Dapper

Dapper es el ORM en el que se basa Stack Overflow y algunas otras webs.

https://code.google.com/p/dapper-dot-net/

Según los benchmarks en su web, llega a ser bastante más rápido que Entuty Framework y Nhibernate en realizar los Selects.

Dapper se puede usar a partir del Framework 3.5, aunque es recomendable Framework a partir de 4 para usar el potencial de las clases dynamic

Vamos a trastear un poco con él a ver cómo funciona.


Instalación
En primer lugar, decir que se trata de un método extensor de IDbConnection, por lo que podemos utilizar cualquier objeto que implemente IDbConnection( Sql Server, Oracle, MySql, ...)

Podemos descargarlo a través de NuGet, o directamente adjuntando la clase SqlMapper.cs a vuesto proyecto.


Consultas sin objetos mapeados
Para obtener una lista de objetos dinamic sin tener que usar ninguna clase:
            

string connectionString = "Data Source=(localdb)\\v11.0;Initial Catalog=NorthWind;Integrated Security=True";
IDbConnection conn= new SqlConnection(connectionString);
conn.Open();

var empleados = conn.Query("select * from employees where country = @pais", new { @pais = "UK" });
foreach (var empleado in empleados)
     Console.WriteLine("{0} {1} - {2}", empleado.FirstName, empleado.LastName, empleado.Country);
conn.Close();
Console.ReadKey();
Nótese que estamos usando Parameters en una clase anónima, por lo que evitamos inyección de SQL.

Consultas sin objetos mapeados en .Net 3.5
Si estuviéramos trabajando con Framework 3.5, bastará con añadir el símbolo de compilación condicional "CSHARP30" en las propiedades del proyecto - Compilar, y obtendremos los valores en IDictionary
var empleados = conn.Query("select * from employees where country = @pais", new { @pais = "UK" });
foreach (var empleado in empleados)
     Console.WriteLine("{0} {1} - {2}", empleado["FirstName"], empleado["LastName"], empleado["Country"]);

Consultas con objetos mapeados
Ahora añadimos una clase POCO de Empleados, y veamos que sigue funcionando, esta vez devolviendo un IEnumerable<T>
public class Employees
{
    public int EmployeeId;
    public string LastName;
    public string FirstName;
    public string Country;
}


var empleados = conn.Query<employees>("select * from employees where country = @pais", new { @pais = "UK" });
foreach (var empleado in empleados)
     Console.WriteLine("{0} {1} - {2}", empleado.FirstName, empleado.LastName, empleado.Country);
El mapeo que realiza Dapper es la coincidencia del nombre del campo y del nombre de la propiedad de la clase. Si hay alguna propiedad que difiera de los campos de la clase, simplemente no lo mapeará.

Actualizaciones, inserciones y borrados
Para realizar operaciones de escritura usaremos los siguientes ejemplos:

Observa que se pueden ejecutar varias líneas dentro de la sentencia.
conn.Execute(@"set identity_insert employees on;
                insert into employees (EmployeeId, FirstName, LastName, Country) values (@EmployeeId, @FirstName, @LastName, @Country);
                set identity_insert employees off;"
                , new { FirstName = "Oswaldo", EmployeeId = 21, LastName = "Rodriguez", Country = "Cuba" });


conn.Execute("update employees set firstname=@FirstName where employeeId=@EmployeeId", new { FirstName = "Leopoldo", EmployeeId = 21 });

También se pueden realizar operaciones masivas pasando una lista de objetos.
var empleados = conn.Query>empleado<("select * from employees where country = @pais", new { @pais = "UK" });
foreach (var empleado in empleados)
     empleado.FirstName = "-" + empleado.FirstName;
conn.Execute("update employees set firstname=@FirstName where employeeId=@EmployeeId", empleados.Select(x=>new {FirstName=x.FirstName, EmployeeId=x.EmployeeId}));

Agregados
var sql="Select * from products p left join categories c on p.CategoryID=c.CategoryID";
var products = conn.Query>Producto, Categoria, Producto<(sql, (prod, cat) => { prod.categoria = cat; return prod; }, splitOn:"CategoryID");
Conclusiones
Como podéis ver, puede ser una buena alternativa para determinados proyectos.
Espero que os sea de utilidad.

jueves, 27 de febrero de 2014

Visualizar objetos en el debug de Visual Studio

Una de las cosas que acabo de usar y que llevan desde el Framework 2 entre nosotros es cómo cambiar el modo de visualizar los objetos en el depurador.

Imaginad que queréis ver lo que hay en una lista de objetos, y os encontráis con esta imagen:














Para tener una visión general de los datos que contiene, tienes que recorrerte la lista e ir seleccionando cada elemento.

Estos son los momentos en los que echas de menos el DataTip que tienen los Datasets, que te mostraba una grid con los datos.



Hay varias soluciones para ello.

  • Una solución es usar DebuggerDisplayAttrubute en la clase. Con ello estamos diciendo al debugger cómo tiene que visualizar los datos. [Más info]


  • Otra solución es implementar dentro de la clase el método "ToString()", devolviendo el formato que queramos.



Otras soluciones, algo más elaboradas, pasan por crear un proxycrear nuestro propio visualizador.

Saludos.



---Ampliación Octubre-2014.
He encontrado un post de Jorge Serrano que propone el uso del atributo  DebuggerBrowsable para cambiar la forma de la que el depurador visualiza los objetos.

martes, 11 de febrero de 2014

Procesos asíncronos con Async Await

Esta es la segunda entrega de la serie que dedico a los procesos asíncronos.

La primera entrega la puedes consultar en este enlace.

Como dijimos anteriormente, con el Framework 4.5 se incluyen algunas instrucciones nuevas en la TPL (Task Parallel Library) como son async, await, y otras contenidas en Task (Delay, FromResult, Run, WhenAll, WhenAny)

Si bien los comandos Async Await se pueden conseguir hacerlos funcionar a partir de VS2012 con el Framework 4.0 importando desde NuGet las librerías Microsoft.Bcl.Async (subconjunto de las TPL del 4.5), el resto de comandos solo están disponibles con el framework 4.5

Un poco de código

Supongamos que volvemos a tener ese proceso largo que nos paraliza la ejecución del hilo.

Lo primero que deberíamos de hacer es encapsularlo dentro de una función que devuelva un Task<tipo>, donde tipo es la devolución de la función.
Si la función no devuelve nada, podremos devolver un Task.
Se recomienda que la función tenga un nombre acabado en "async" por claridad, y que devuelva un Task. Se podría devolver un void, pero no es lo recomendable (Aquí y aquí comentan las razones por las que no recomiendan void functions)

private static Task<string> ProcesoLargoAsync (string texto)
{
     Task<string> t = Task.Run(() => {
          int tiempo = new Random().Next(1000, 6000);
          Thread.Sleep(tiempo);
          string texto2 = texto.ToUpper();
          return texto2;
     });
     return t;
}

Task.Run (que es nuevo en el 4.5) cumple el mismo cometido que Task.Factory.StartNew: Declarar y arrancar el proceso.

A continuación, llamaremos a esta función que devuelve una tarea con otra que es la que la marcaremos como asíncrona.
public static async void PruebaDeAsync0()
{
     string texto = await ProcesoLargoAsync("Hello world!!!");
     Console.WriteLine(texto);
}

Y la llamaremos normalmente.
Console.WriteLine("Empezamos hilo principal con Async-Await");
PruebaDeAsync0();
Console.WriteLine("Hilo principal acabado");
En el momento que el hilo de ejecución pase por la función marcada como async, la ejecutará un segundo hilo, parándose en el await hasta que la función ProcesoLargoAwait responda, y, a continuación, imprimirá el resultado por consola.
Mientras, el hilo principal no se ha detenido y ha impreso el "Hilo principal acabado".

Listas

Mediante las funciones Task.whenAny o Task.WhenAll podremos controlar la ejecución de las tareas
public static async void PruebaDeAsync1()
{
    List<Task<string>> lista = new List<Task<string>>()
        ProcesoLargoAsync("Hello world 1 !!!"),
        ProcesoLargoAsync("Hello world 2 !!!"),
        ProcesoLargoAsync("Hello world 3 !!!"),
        ProcesoLargoAsync("Hello world 4 !!!"),
        ProcesoLargoAsync("Hello world 5 !!!")
    };

    var y = await Task.WhenAny(lista);
    Console.WriteLine("WhenAny: Se ha acabado la tarea {0}", y.Result);
    var x = await Task.WhenAll(lista);
    Console.WriteLine("Todas las tareas acabadas");
}

La llamada a la función:

Console.WriteLine("Empezamos hilo principal de listas Async-Await");
PruebaDeAsync1();
Console.WriteLine("Hilo principal acabado");
 
En este caso la instrucción await Task.WhenAny(lista) bloqueará el hilo asíncrono hasta que alguna tarea acabe.
La instrucción await Task.WhenAll(lista) volverá a bloquear el hilo asíncrono hasta que todas las tareas acaben.
También se podría haber llamado a cada tarea y haberle aplicado un ContinueWith para que cuando acabe cada tarea notifique que ha acabado.
List<Task<string>> lista = new List<Task<string>>()
{
    ProcesoLargoAsync("Hello world 1 !!!"),
    ProcesoLargoAsync("Hello world 2 !!!"),
    ProcesoLargoAsync("Hello world 3 !!!"),
    ProcesoLargoAsync("Hello world 4 !!!"),
    ProcesoLargoAsync("Hello world 5 !!!"),
    ProcesoLargoAsync("Hello world 6 !!!"),
    ProcesoLargoAsync("Hello world 7 !!!"),
    ProcesoLargoAsync("Hello world 8 !!!"),
    ProcesoLargoAsync("Hello world 9 !!!"),
    ProcesoLargoAsync("Hello world 10 !!!")
};

lista.ForEach(tarea=>tarea.ContinueWith((tareaEjecutada)=>
    Console.WriteLine("Ha acabado la tarea "+tareaEjecutada.Result)));

await Task.WhenAll(lista);
Console.WriteLine("Todas las tareas acabadas");

Interfaces de usuario

En esta parte es donde más se aprecia el cambio.
Vimos en las TPL 4.0 que teníamos que andar con Invoke para poder ejecutar un código asíncrono en una interfaz ya que un proceso no tenía visibilidad sobre otro proceso.
Con la TPL 4.5 podemos hacer algo tan sencillo como:

private void button2_Click(object sender, EventArgs e)
{
    TareaAsync();
}

public async void TareaAsync()
{
    label1.Text = await ProcesoLargoAsync("Hello, world!!!");
}


Saludos.