sábado, 2 de septiembre de 2017

Compativilidad de UWP con NETStandard 2.0


En los últimos días ha salido una nueva versión de Visual Studio 2017 (la 15.3) en la que se ha mejorado considerablemente la compatibilidad con proyectos NETStandard y la aparición de la versión 2.0 de estos. También disponemos de la nueva versión de EntityFrameworkCore 2.0.

Ahora llegan los problemas. NETStandard 2.0 no es compatible con UWP Build 15063. Lo anecdótico de esto, es que con proyectos para iOS y Android funciona perfectamente.Ya se está hablando de una versión de Visual Studio 15.4, con soporte para UWP Build 16267, que posiblemente aparezca con Windows 10 Fall Creators Update. Ahora mi duda es, ¿Qué pasa con los móviles que hay circulando todavía con Windows 10, muchos de ellos que quedaron en Annirversary Update?

Por lo visto, todos estos cambios son debido a que NET Standard 2.0 se parece más a .NET Framework y quieren fomentar la migración de aplicaciones antiguas.

lunes, 14 de agosto de 2017

Comprabar si tenemos conexión en Android con Xamarin

Con este sencillo ejemplo podremos comprobar si tenemos conexión desde un terminal Android desde una App desarrollada con Xamarin.


private bool IsNetworkAvailable(Context context)
{
       ConnectivityManager connectivity =
           (ConnectivityManager)context.GetSystemService(Context.ConnectivityService);
  
    if (connectivity != null)
    {
        var activeNetworkInfo = connectivity.ActiveNetworkInfo;
        if (activeNetworkInfo != null && activeNetworkInfo.IsConnectedOrConnecting)
        {
            return true;
        }
    }
    return false;
}

sábado, 5 de agosto de 2017

Actualizar paquetes NuGet

En algunos tipos de proyectos de Visual Studio, cuando migramos a una versión más moderna del framework, si miramos en el fichero packages.config del proyecto veremos que en algunos de los paquetes nos encontramos con la etiqueta requireReinstallation. Los paquetes NuGet dependiendo de la versión del framework instalan diferentes ficheros. Así que nos está indicando que dicho paquete tiene una configuración distinta para el nuevo framework seleccionado, que para el que teníamos seleccionado cuando instalamos dicho paquete.

para solucionar este problema, vasta con irnos a la "Package Manager Console" y ejecutar el comando.

Update-Package -Reinstall

Esto reinstalará todos nuestros paquetes con las características del framework seleccionado.

viernes, 7 de abril de 2017

Compativilidad Hyper-V con otros motores de máquinas virtuales

Para el desarrollo de dispositivos móviles a menudo tenemos que lidiar con varios tipos de máquinas virtuales. El problema es que algunas funcionan sobre Hyper-V y otras sobre otros motores de virtualización, los cuales no son compatibles. Para no tener que estar instalando y desinstalando, se puede habilitar y deshabilitar el Hypervisor de Hyper-V y habilitarlo cuando lo volvamos a necesitar. Para ello vasta con ejecutar los comandos.

Deshabilitar Hypervisor

bcdedit /set hypervisorlaunchtype off


Habilitar Hypervisor

bcdedit /set hypervisorlaunchtype auto

jueves, 9 de marzo de 2017

Pruebas unitarias con Entity Framework Core

Las pruebas unitarias contra base de datos siempre son complicadas. Ya que en muchas ocasiones no podemos crear una base de datos vacía para nuestras pruebas. Si utilizamos Entity Framework esta tarea se hace muy sencilla, con este sencillo truco. En la que creamos una base de datos al inicializar el test y la borramos al terminarlo.

Para ello deberemos utilizar los métodos EnsureCreated y EnsureDeleted, las cuales crean y borran una base de datos de una forma muy sencilla.

[ClassInitialize()]
public static void InitDataBase(TestContext context)
{
    using (var db = new MyDbContext())
    {
        db.Database.EnsureCreated();
    }
}

[ClassCleanup]
public static void DeleteDataBase()
{
    using (var db = new MyDbContext())
    {
        db.Database.EnsureDeleted();
    }
}

lunes, 6 de marzo de 2017

Particionar base de datos con Entity Framework Core

Supongamos que necesitamos dar soporte a varios clientes con una única aplicación. Por ejemplo ofreciendo SAAS (Software as a service). En la que tenemos el mismo software para todos los clientes, pero sus datos son independientes. La forma más sencilla seria crear una instancia de base de datos para cada cliente. Pero esto es costoso y no siempre viable, sobretodo si tenemos muchos clientes con un volumen de datos pequeño por cliente.

Azure nos ofrece la posibilidad de crear grupos elásticos. Pero estos están limitados a un máximo de 500 bases de datos. Aunque parecen muchas, es posible que tengamos más clientes y la mayoría de ellos inactivos. Con lo que está opción no es siempre viable.

Otra forma es marcar cada registro en base de datos con un campo instancia. En el que identificamos a que cliente o instancia pertenece da registro. Teniendo que insertar y meter en todas nuestras consultas la referencia a la instancia.

Si utilizamos Entity Framework Core, estre trabajo se puede automatizar, quedando de una forma transparente para la mayoría de desarrolladores.

Al definir las entidades del modelo. Deberemos introducir un campo en el que indicaremos a que partición pertenece el registro. Para ello crearemos una "propiedad sombra" la cual nos permite enlazar a un registro de base de datos, sin la necesidad de asociarlo a un registro en nuestra entidad.

modelBuilder.Entity<Person>(entity =>
{
   entity.Property<int>("IdPartition");
});

Para hacerlo más trasparente. Nos crearemos una clase PartitionValueGenerator que herede de ValueGenerator, la cual nos permitirá generar un valor automáticamente a nuestra propiedad. Así nos evitaremos la necesidad de darle el valor, cada vez que creamos un objeto.

public class PartitionValueGenerator : ValueGenerator<int>
{
    public override int Next(EntityEntry entry)
    {
        return ((MyDbContext)(entry.Context)).IdPartition;
    }

    public override bool GeneratesTemporaryValues => false;
}

Y se lo asignaremos a nuestra propiedad

modelBuilder.Entity<Person>(entity =>
{
     entity.Property<int>("IdPartition")
         .HasValueGenerator((p, e) => new PartitionValueGenerator(););
});

Con esto ya conseguimos insertar un valor de forma transparente en nuestro registro. Ahora vamos ha definir como hacer las consultas. Para ello necesitamos definirnos una versión personalizada de DbSet. Con la que podremos modificar el objeto Expression antes de lanzar la consulta. Redefinimos la propiedad IQueryable.Expression de la siguiente forma.


public class PartitionalDbSet<TEntity, TIdPartition> : DbSet<TEntity>,
            IQueryable<TEntity>, IAsyncEnumerableAccessor<TEntity>, Infrastructure<IServiceProvider>
        where TEntity : class
{
..... 

Expression IQueryable.Expression
{
    get
    {
        Expression dbExpression = ((IQueryable)mDbSetBase).Expression;
        TIdPartition idPartition = mIdPartition;

        Expression<Func<TEntity, bool>> expresionFuncFilter = b => EF.Property<TIdPartition>(b, "IdPartition").Equals(idPartition);

        IQueryable<TEntity> source = null;
        Expression<Func<TEntity, bool>> predicate = null;

        var meth = GetMethodInfo<IQueryable<TEntity>, Expression<Func<TEntity, bool>>,
                    IQueryable<TEntity>>(new Func<IQueryable<TEntity>, Expression<Func<TEntity, bool>>, IQueryable<TEntity>>
                        (Queryable.Where<TEntity>), source, predicate);

         Expression expression = Expression.Call(null, meth, dbExpression, expresionFuncFilter);

    return expression;
    }
}

Ya solo nos queda definir los DbSet en nuestra contexto.

private DbSet<Person> mPersons;

public DbSet<Person> Persons
{
    get
    {
        if (mPersons == null)
        {
           mPersons = new PartitionalDbSet<Person, int>(base.Set<Person>(), mIdPartition);
        }
        return mPersons;
    }
}
Con esto podremos definir diferentes instancias del contexto de base de datos, para diferentes clientes o subconjuntos de datos, de una forma muy sencilla y trasparente.

using (var db = new MyDbContext(1))
{
    Person person = new Person()
    {
         Name = "Name 1",
         Description = "Description 1"
    };

    db.Persons.Add(person);
    await db.SaveChangesAsync();
}

using (var db = new MyDbContext(1))
{
     var person = await db.Persons.Where(p => p.Name.StartsWith("Name")).ToListAsync();
     Assert.IsTrue(person.Count() > 0);
}

Si os interesa este tema lo podéis explorar con más detenidamente descargado un ejemplo en:
https://github.com/andrechi1/Blog-Examples/tree/master/PartitionEFCore

lunes, 6 de febrero de 2017

Buenas practicas con Async/Await

Con la aparición de los procesadores con varios núcleos se ha vuelto critico el saber manejar la multitarea. Desde la primera versión del Framework de .Net existe el espacio de nombre System.Threading, el cual se puede considerar un wrappear para acceder a las directivas de sincronización del sistema, acceder al pool de hilos o crear nuestros propios hilos.

Posiblemente con System.Threading se puede realizar cualquier tarea. Pero la dificultad de su uso y mantenimiento han invitado a crear otro tipo de librerías más sencillas.

Primero se abordo la multitarea de CPU. Con una nueva clase para manejar tareas que es Task, un controlador llamado Parallel y una serie de clases para manejar colecciones de forma asíncrona. Esto nos permite aprovechar los diversos núcleos de los procesador actuales. Permitiendo lanzar tareas en paralelo y sincronizarlas de una forma sencilla.

Pero había un escenario que seguia siendo complicado. Y con la aparición de los entornos táctiles se empezó a ver la importancia de esto. Me refiero a la posibilidad de no bloquear ciertos recursos de la máquina.

Es importante entender la diferencia entre los dos escenarios de los que hablo. No es lo mismo la multitarea de CPU que la multitarea de IO. Y es importante entenderla bien.En este articulo nos centraremos en la multitarea de IO, o como no bloquear recursos de la máquina. Para esto a partir del Framework 4.5 se introdujeron Async/Await, que nos facilitan menormente el trabajo.

Otro concepto que hay que entender bien es el contexto de dispositivo. Los contextos de dispositivos los crea Windows y nos permiten pintar sobre la pantalla u otro dispositivo. Tanto en WinForm como WCF solo disponen de un contexto de dispositivo por aplicación. Esto significa que solo puede pintar un hilo determinado sobre la pantalla.

Una forma de invocar al contexto de dispositivo es mediante los eventos comunes, como OnClick, OnMouseMove. Todos los eventos y sobrecargas de la clase Form (en WinForm) o Window en (WPF) se invocan a traves del contexto de dispositivo. Otra forma de invocarlo es mediante el método Invoke (en WinForm) o a traves de la clase  Dispatcher en (WPF). En todos los casos hay que seguir una regla de oro. Mantener el hilo ocupado el menor tiempo posible.

Una casa que hay que entender de Async/Await, es que en principio nuestra aplicación no va a funcionar más rápido. Ya que Async/Await creará hilos y bloqueos por nosotros y estos consumen recursos del sistema. Así que solo usarlo donde sea necesario y se produzcan bloqueos de IO, como acceso a base de datos, a disco u servicios Web.

Async/Await hay que llevarlo hasta el final. Por ejemplo, desde la captura de nuestro evento, hasta el acceso a la base de datos.

No utilizar Async/Await para realizar tareas costosas en las que interviene el procesador. Por ejemplo, eso es una manera muy sencilla de no bloquear nuestra aplicación con una tarea costosa. Pero hay otra formas más elegante, creando una buena arquitectura Modelo Vista ViewModel.

private async void Button_Click(object sender, RoutedEventArgs e)
{
    await Task.Run(() =>
    {
       // Tarea costosa.
    });
}
Si tenemos una clase intermedia que no va a gestionar ningún tipo de bloqueo no utilizar Async/Await. Recordar que el compilador meterá mucho código por nosotros que conlleva sobrecarga en el sistema.

private Task AccesoADatos()
{
   int i = 54;
   return MiDDBB.CreateQueryAsync(i);
}
en vez de

private async Task AccesoADatos()
{ 
     int i = 54;
     await MiDDBB.CreateQueryAsync(i);
}