EF 6 upgrading from old versions

If you try to upgrade your components or applications to EF 6  from older versions, you could observe that compilation fails. It is because

Etiquetas de Technorati:

Microsoft broke the backward compatibility by any reason. But its easy to fix it.

First of all, is upgrade by installing Entity Framework desde nuget, this remove older versions of EF and should remove System.Data references too. But in several cases does not do it. In this case you must remove it.

To fix follow below steps:

  1. Install EF 6 from nuget.
  2. Remove references to System.Data.Entity.
  3. Update namespaces of System.Data.Entity to System.Data.Entity.Core

This procedure fix the compilation issues in most cases, but if you continue having problems you should review next page from MSDN.: http://msdn.microsoft.com/en-US/data/upgradeEF6

 

There are other possible accesibility issues to classes ObjectContext and DbContext.

How get count of an entitySet in Lightswitch

Many people have several problems when work with entitySets in lightswitch. EntitySet are objects that implements IDataServiceQueryable instead IQueryable so it doesnt have access to many linq extension methods.

Two of these are ToList() and Count().

But it implements IExecutable which get us access to Execute() method that return an IEnumerable<> of this EntitySet. The Execute() method executes a query over the EntitySet.

Simply, use the Execute method as below code:

  1. var myCol = DataWorkspace.JoincatalogsData.Categories.Where(m => m.KeyId == “DEFAULT”).Execute();
  2. var myColCount = myCol.Count();

In this case ToList() is not necessary because the Execute() method returns a IEnumerable.

I hope this can help!.

Asp.Net Web API: Custom return format

¿Como cambiar el formato de los resultados devueltos por un servicio mediante un parametro en la url de la solicitud GET?.

Pues es muy sencillo.

Tenemos que agregar a la configuración del servicio, los formatters que queremos usar. Lo más común es usar Xml y Json.

Añadimos al Global.asax el siguiente código:

  1. GlobalConfiguration.Configuration.Formatters.Clear();
  2. GlobalConfiguration.Configuration.Formatters.Add(new XmlMediaTypeFormatter());
  3. GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());

Y despues vamos a configurar que: mediante un parametro “format” podamos indicar en la consulta el formato deseado: Xml o Json.

Agregamos la línea:

  1. GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(
  2.                 new QueryStringMapping(“format”, “json”, “application/json”)
  3.                 );

De esta forma estamos configurando un comportamiento del servicio para que cuando reciba un parametro “format=json” utilice el formatter “JsonMediaTypeFormatter” y devuelva los datos en Json.

Como hemos añadido en primer lugar el formatter “XmlMediaTypeFormatter”, el formato por defecto será XML.

Y voila: http://myservice/data?format=json devolverá Json y http://myservice/data devolverá Xml.

Mas sencillo imposible, ¿No?.

Many to many relationships in Code First. sobre la misma entidad

En muchos modelos se necesitan relaciones muchos a muchos sobre la misma entidad. Esto que parece algo más complicado, es realmente muy sencillo. Pero hay que hacer uso de Fluent API para configurar las foreignKeys.

Normalmente se necesita para establecer jerarquía entre objetos del mismo tipo (entidad). En el siguiente ejemplo vamos a definir un jerarquía de categorías en la que un categoría puede tener varias categorías hija y a su vez pertenecer a varias categorías padre.

Primero definimos nuestra clase “Category” con 2 propiedades de navegacion a si misma.

  1. public partial class Category
  2. {
  3.     [Key]
  4.     public int CategoryId { get; set; }
  5.     [Required, MaxLength(100)]
  6.     public virtual string Name { get; set; }
  7.     public virtual ICollection<Category> ParentCategories { get; set; }
  8.     public virtual ICollection<Category> ChildCategories { get; set; }
  9. }

Creamos la propieda del contexto para nuestra entidad.

  1. public DbSet<Category> Categories { get; set; }

 

public DbSet<Category> Categories { get; set; }

Una vez definida la entidad y las propiedades de navegación, dentro de la clase del contexto sobreescribimos el método OnModelCreating que nos da acceso al objeto ModelBuilder que usaremos para personalizar nuestro modelo a través Fluent API.

Muy importante es establecer correctamente las claves de los extremos de la relación. “Left” corresponde a la clave para la propiedad que establecemos en el método “HasMany” y el mapeo de la clave “Right” corresponde a la clave para la propiedad del método “WithMany”.

  1. protected override void OnModelCreating(DbModelBuilder modelBuilder)
  2. {
  3.     //Catalog and categories
  4.     modelBuilder.Entity<Category>().HasMany(c => c.ParentCategories)
  5.     .WithMany(a => a.ChildCategories)
  6.     .Map(t =>
  7.         {
  8.             t.ToTable("Catalog");
  9.             t.MapLeftKey("ChildCategoryId");
  10.             t.MapRightKey("ParentCategoryId");
  11.  
  12.         });
  13. }

Y voila, si tenemos activado la opcion de Migrations nos actualizará nuestra base de datos con 2 tablas: la primera con nombre “Category” para las entidades y una segunda tabla “Catalog” que mantiene la relación con las correspondientes foreignKeys.

Espero  que os valga, como véis ha sido muy sencillo.

EF 5 no soporta XML data types

Entity Framework no soporta XML como EntityDataType y esto puede ser un problema en determinados escenarios.

El siguiente snippet permite usar el tipo XElement en nuestro modelo aunque no podremos usar esta propiedad directamente en nuestras queries linq.

  1. /// <summary>
  2. /// Global values for localization. In xml format.
  3. /// </summary>
  4. public virtual string GlobalValues { get; set; }
  5. [NotMapped]
  6. public XElement GlobalValuesWrapper
  7. {
  8.     get { return XElement.Parse(GlobalValues); }
  9.     set { GlobalValues = value.ToString(); }
  10. }

Es simple pero sirve para lo que se pretende.

Supongo que el soporte de XML es muy complejo y espero que venga soportado en futuras revisiones.

Many to Many relationships in Code First

El mejor modo de configurar las relaciones “Many to  Many” en code first es usando fluent API, con fluent API podemos hacer cualquier configuración en nuestro modelo cosa que no podemos hacer con las convenciones de atributos.

No es  que no crea que los atributos no son útiles, que realmente lo son, sino que es ocasiones y para determinadas configuraciones es mejor y más sencillo usar fluent api.

Partiendo por  ejemplo de 2 clases “Customer” y “Video”, en un escenario en el que un “Customer” puede haber alquilado varios “Videos” y un mismo video puede haber sido alquilado por varios “Customers”. Cada clase tendría las siguientes propiedades de navegación:

  1. public class Customer
  2. {
  3.     [Key]
  4.     public int CustomerId { get; set; }
  5.     public virtual ICollection<Video> Videos { get; set; }
  6. }
  7. public class Video
  8. {
  9.     [Key]
  10.     public int VideoId { get; set; }
  11.     public virtual ICollection<Customer> Customers { get; set; }
  12. }

En nuestra clase de definición del contexto podemos usar el objeto “ModelBuilder” de Fluent API:

  1. public class VideoClubContext : DbContext
  2. {
  3.     public DbSet<Customer> Customers { get; set; }
  4.     public DbSet<Video> Videos { get; set; }
  5.     //Sobreescribimos el mtodo OnModelCreating que nos da acceso al Objeto ModelBuilder.
  6.     protected override void OnModelCreating(DbModelBuilder modelBuilder)
  7.     {
  8.         modelBuilder.Entity<Customer>()
  9.                 .HasMany(customer => customer.Videos)
  10.                 .WithMany(video => video.Customers)
  11.                 .Map(t =>
  12.                 {
  13.                     t.ToTable("VideoHistory");
  14.                     t.MapRightKey("VideoId");
  15.                     t.MapLeftKey("CustomerId");
  16.                 });
  17.     }
  18. }

Y voila, cuando ejecutemos nuestra aplicación, y dependiendo de nuestra configuración de “Migrations”, se creará en nuestra base de datos una tabla “Customers”, una  tabla “Videos” y una tercera tabla “VideoHistory” con las columnas: “CustomerId” y “VideoId” configuradas como foreingKeys de “Customers” y “Videos”.


Por favor no dejéis de leer los libros de Julie Lerman “Programming Entity Framework: Code First” y “Programming Entity Framework: DbContext”, ambos de O’reilly.

Os ayudarán muchísimo.

Convertir Json a C#

Cuando trabajemos con MVC y Rest web service, nos encontraremos tarde o temprado con la necesidad de convertir objetos JSON en colleciones tipadas de nuestras propias clases.

Utilizando la librería para Json.NET (Newtonsoft)  lo podemos hacer de una forma rápida limpia y sencilla:

Para este ejemplo  usamos un objecto Json con una colección de categorías, y para hacer el ejemplo un poco más complejo la colección es un propiedad del objecto JSON (no el propio objecto Json) y las categorías tienen hijos que son a su vez categorías.

El objeto Json sería como el siguiente:

   1: {

   2:   "CategoriesCount": 0,

   3:   "Categories": [

   4:     {

   5:       "Id": 1,

   6:       "Name": "Plastico militar",

   7:       "Description": null,

   8:       "KeyId": "PLAST-MIL",

   9:       "Childs": [

  10:         {

  11:           "Id": 2,

  12:           "Name": "Plastico militar 1/35",

  13:           "Description": null,

  14:           "KeyId": "PLAST-MIL-135",

  15:           "Childs": null,

  16:           "IsRootCategory": false

  17:         },

  18:         {

  19:           "Id": 3,

  20:           "Name": "Plastico militar 1/48",

  21:           "Description": null,

  22:           "KeyId": "PLAST-MIL-148",

  23:           "Childs": null,

  24:           "IsRootCategory": false

  25:         }

  26:       ],

  27:       "IsRootCategory": true

  28:     },

  29:     {

  30:       "Id": 2,

  31:       "Name": "Plastico militar 1/35",

  32:       "Description": null,

  33:       "KeyId": "PLAST-MIL-135",

  34:       "Childs": [],

  35:       "IsRootCategory": false

  36:     },

  37:     {

  38:       "Id": 3,

  39:       "Name": "Plastico militar 1/48",

  40:       "Description": null,

  41:       "KeyId": "PLAST-MIL-148",

  42:       "Childs": [],

  43:       "IsRootCategory": false

  44:     }

  45:   ]

  46: }

Queremo convertir este objeto en una lista tipada de una clase “Category” por lo que la clase “Category” debe tener las misma propiedades públicas que un elemento de la colección “Categories” del objeto Json.

Observamos que además esta clase posee una propiedad “Childs” que es a su vez una colección de objetos “Category”:

   1: public class Category

   2: {

   3:     public int Id { get; set; }

   4:     public string Name { get; set; }

   5:     public string Description { get; set; }

   6:     public string KeyId { get; set; }

   7:     public List<Category> Childs { get; set; }

   8:     public bool IsRootCategory { get; set; }

   9: }

 

Para convertir el objeto Json a nuestra lista genérica usaremos el método “Deserialize” de la clase “JsonConvert” de  la librería Json.NET, que se puede agregar desde nuGet: Json.NET Download

   1:  

   2: List<Category> Categories = (List<Category>)JsonConvert.DeserializeObject(myJsonCategories["Categories"].ToString(), typeof(List<Category>));

   3:  

 

Y voila, ya tenemos nuestra lista genérica dispuesta a ser consumida.

Espero que os pueda ser útil.

EF 5 problemas con DataAnnotations

En algunos casos es posible que surjan algunos conflictos de espacios de nombre entre el ensamblado “EntityFramework” y el ensamblado “System.Data” de .Net Framework 4.5.

Pues bien la última versión del ensamblado “EntityFramework” resuelve estos problemas, la versión del ensamblado debe ser 5.0.0 y no 4.4.0.

La versión 4.4.0 es para utilizarla con los proyectos con target al .Net Framework 4.0.

Espero que os sirva.

Entity Framework 4.3 Usando Migrations

En la versión de Entity Framework 4.3.1 que se ha revisado recientemente en Abril 2012 se incorpora por primera vez el módulo Migrations que permite mantener el esquema de la base de datos sincronizada con los cambios en nuestro modelo cuando usamos EF Code First.

EF 4.3.1 sólo esta disponible desde Nuget y debemos instalarlo usando el Nuget package manager.

Cuando instalamos EF 4.3.1 disponemos de nuevos tags de configuración para establecer el comportamiento de EF de forma declarativa. Esto es posible añadiendo nueva sección de configuración para entity framework que habilita estos tags:

image

Y que debemos asegurarnos de incluir en nuestros archivos de configuración si queremos usar la configuración de EF disponible en esta versión.

EF 4.3. Migrations incorpora 2 maneras de mantener sincronizada la base de datos con nuestro modelo: una primera de forma automatizada cada vez que se inicia la aplicación oy otra de forma manual ejecutando los comandos powershell que se instalan junto con EF 4.3.1

http://coding.abel.nu/2012/03/ef-migrations-command-reference/

Para poder usar Migrations con el proyecto de nuestro modelo de negocio, es necesario habilitar Migrations para el proyecto.

Comenzaremos abriendo la ventana del  “Package Manager Console” y ejecutamos el comando “Enable-Migrations”. Es muy importante seleccionar el proyecto sobre el que queremos habilitar Migrations:

 

image

Esto nos creara en nuestro proyecto una carperta “Migrations” con una clase “Configuration” en la que podremos  definir algunas de las características de comportamiento de Migrations como la activación de las actualizaciones automáticas, o, podremos incluir código especializado para el mapeo de nuestro modelo sobre la base de datos usando Fluent API :

image

image

En este post no centraremos en la capacidad que nos ofrece Migrations para mantener nuestra base de datos y nuestro modelo sincronizados  de forma manual. Para esto desactivaremos en primer lugar las actualizaciones automáticas como en el siguiente ejemplo:

   1: namespace Events.Data.Migrations

   2: {

   3:     using System;

   4:     using System.Data.Entity;

   5:     using System.Data.Entity.Migrations;

   6:     using System.Linq;

   7:  

   8:     internal sealed class Configuration : DbMigrationsConfiguration<Events.Data.EventContext>

   9:     {

  10:         public Configuration()

  11:         {

  12:             AutomaticMigrationsEnabled = false;

  13:         }

  14:  

  15:         protected override void Seed(Events.Data.EventContext context)

  16:         {

  17:             //  This method will be called after migrating to the latest version.

  18:  

  19:             //  You can use the DbSet<T>.AddOrUpdate() helper extension method 

  20:             //  to avoid creating duplicate seed data. E.g.

  21:             //

  22:             //    context.People.AddOrUpdate(

  23:             //      p => p.FullName,

  24:             //      new Person { FullName = "Andrew Peters" },

  25:             //      new Person { FullName = "Brice Lambson" },

  26:             //      new Person { FullName = "Rowan Miller" }

  27:             //    );

  28:             //

  29:         }

  30:     }

  31: }

 

Las migraciones automáticas las veremos en un siguiente post, pero considero que es mejor controlar las migraciones de forma manual y por eso comenzamos revisando este alternativa en primer lugar.

Crear una migración

Una vez habilitado MIgrations y una vez definido nuestro modelo (al menos en su mayor parte), podemos proceder  a preparar una migración. Para preparar una migración disponemos del comando:

Add-Migration:

Lo mas probable cuando usanmos code first es que partamos de una base de datos vacía, en cuyo caso “Add-Migration”  generará el código necesario para crear nuestras tablas completas con sus relaciones, claves, foreingKeys, etc… y creará también el snapshot que se almacenará en la tabla  (_MigrationHistory) que mantiene la historia de las migraciones.

Cada vez que se ejecuta el comando “Add-Migration” se compara el modelo con el último snapshot para determinar los cambios a realizar.

El comando “Add-Migration” necesita que le especifiquemos un nombre de migración, EF generará un fichero con el código necesario para realizar los cambios en la base de datos. El nombre de este fichero será el nombre que le hayamos proporcionado como parametro en el comando “Add-Migration” con un prefijo que la agrega EF basado en un timestamp, de forma que cada migración tenga un nombre único que la pueda identificar. Este comando necesita que le indiquemos la cadena de conexión que se utilizará para la conexión de la migración, hay varias formas de hacerlo pero en este ejemplo me ha decantado por usar el parametro:

–StartupProjectName = ‘Events.Data’

Que apunta a un proyecto con un app.Config que contiene la cadena de conexión para mi base de datos de SQL Server CE 4.0:

image

 

image

image

Si la base de datos está vacia, el código generado será parecido al siguiente:

   1: namespace Events.Data.Migrations

   2: {

   3:     using System.Data.Entity.Migrations;

   4:     

   5:     public partial class MyMigration1 : DbMigration

   6:     {

   7:         public override void Up()

   8:         {

   9:             CreateTable(

  10:                 "Events",

  11:                 c => new

  12:                     {

  13:                         Id = c.Int(nullable: false, identity: true),

  14:                         Name = c.String(nullable: false, maxLength: 4000),

  15:                         EventDate = c.DateTime(nullable: false),

  16:                         Title = c.String(maxLength: 30),

  17:                         State = c.Int(nullable: false),

  18:                     })

  19:                 .PrimaryKey(t => t.Id);

  20:             

  21:             CreateTable(

  22:                 "Assistants",

  23:                 c => new

  24:                     {

  25:                         Id = c.Int(nullable: false, identity: true),

  26:                         Alias = c.String(maxLength: 4000),

  27:                         Contact_Id = c.Int(nullable: false),

  28:                         Event_Id = c.Int(),

  29:                     })

  30:                 .PrimaryKey(t => t.Id)

  31:                 .ForeignKey("Contacts", t => t.Contact_Id, cascadeDelete: true)

  32:                 .ForeignKey("Events", t => t.Event_Id)

  33:                 .Index(t => t.Contact_Id)

  34:                 .Index(t => t.Event_Id);

  35:             

  36:             CreateTable(

  37:                 "Contacts",

  38:                 c => new

  39:                     {

  40:                         Id = c.Int(nullable: false, identity: true),

  41:                         Name = c.String(maxLength: 4000),

  42:                         Email = c.String(maxLength: 4000),

  43:                         Phone = c.String(maxLength: 4000),

  44:                     })

  45:                 .PrimaryKey(t => t.Id);

  46:             

  47:             CreateTable(

  48:                 "Speakers",

  49:                 c => new

  50:                     {

  51:                         Id = c.Int(nullable: false, identity: true),

  52:                         Alias = c.String(maxLength: 4000),

  53:                         Contact_Id = c.Int(nullable: false),

  54:                         Event_Id = c.Int(),

  55:                     })

  56:                 .PrimaryKey(t => t.Id)

  57:                 .ForeignKey("Contacts", t => t.Contact_Id, cascadeDelete: true)

  58:                 .ForeignKey("Events", t => t.Event_Id)

  59:                 .Index(t => t.Contact_Id)

  60:                 .Index(t => t.Event_Id);

  61:             

  62:             CreateTable(

  63:                 "Resources",

  64:                 c => new

  65:                     {

  66:                         Id = c.Int(nullable: false, identity: true),

  67:                         Url = c.String(maxLength: 4000),

  68:                         Size = c.Long(nullable: false),

  69:                         BinaryData = c.Binary(maxLength: 4000),

  70:                         Event_Id = c.Int(),

  71:                     })

  72:                 .PrimaryKey(t => t.Id)

  73:                 .ForeignKey("Events", t => t.Event_Id)

  74:                 .Index(t => t.Event_Id);

  75:             

  76:         }

  77:         

  78:         public override void Down()

  79:         {

  80:             DropIndex("Resources", new[] { "Event_Id" });

  81:             DropIndex("Speakers", new[] { "Event_Id" });

  82:             DropIndex("Speakers", new[] { "Contact_Id" });

  83:             DropIndex("Assistants", new[] { "Event_Id" });

  84:             DropIndex("Assistants", new[] { "Contact_Id" });

  85:             DropForeignKey("Resources", "Event_Id", "Events");

  86:             DropForeignKey("Speakers", "Event_Id", "Events");

  87:             DropForeignKey("Speakers", "Contact_Id", "Contacts");

  88:             DropForeignKey("Assistants", "Event_Id", "Events");

  89:             DropForeignKey("Assistants", "Contact_Id", "Contacts");

  90:             DropTable("Resources");

  91:             DropTable("Speakers");

  92:             DropTable("Contacts");

  93:             DropTable("Assistants");

  94:             DropTable("Events");

  95:         }

  96:     }

  97: }

 

En cambio si la base de datos existe y hemos añadido un nuevo campo a nuestro modelo que no existía previamente en el esquema actual, podría ser como el siguiente:

EF crear un archivo de migración con 2 métodos: uno con el código para aplicar los nuevos cambios y otro con el código necesario para deshacer estos cambios, más adelante veremos como podemos hacer esto con el comando Update-Database:

 

   1: namespace Events.Data.Migrations

   2: {

   3:     using System.Data.Entity.Migrations;

   4:     

   5:     public partial class MyMigration2 : DbMigration

   6:     {

   7:         public override void Up()

   8:         {

   9:             AddColumn("Assistants", "Name", c => c.String(maxLength: 4000));

  10:         }

  11:         

  12:         public override void Down()

  13:         {

  14:             DropColumn("Assistants", "Name");

  15:         }

  16:     }

  17: }

 

 

Cada vez que ejecutamos el comando Add-Migration EF nos agrega un nuevo archivo basado en la diferencias encontradas con el snapshot anterior.

image

Aplicar una migración

Una vez creada la migración ha llegado el momento de actualizar la base de datos con estos cambios. Para esto disponemos del comando:

Update-Database

Este comando se encarga de aplicar los cambios generados a nuestra base de datos. De nuevo nos encontramos con 2 escenarios posiobles: el primero cuando la base de datos está vacía y el segundo cuandoi la base de datos ya ha sido inicializada previamente.

Si la base de datos está vacía, el comando Update-Database creará la tabla (_MigrationHistory) además de aplicar los cambios en la bse de datos. También guardará el snapshot generado por el comando Add-Migration en la tabla _MigrationHistory.

Igual que antes, especificamos un proyecto con el archivo de configuración que contiente la cadena de conexión:

image

Y nuestra base de datos será actualizada según los cambios especificados en el archivo de migración.

Cada vez que ejecutamos un comando “Add-Migration” EF crea un nuevo archivo de migración con las diferencias encontradas con el estado anterior de la base de datos. El comando Update-Database también nos permite retroceder a un estado anterior de una migración específica. Lo podemos hacer mediante el parametro –TargetMigration especificando el nombre de una migración existente (mucho mejor si es el nombre completo incluyendo el timestamp):

-TargetMigration: ‘MyMigration1’ o  -TargetMigration: ‘201205021006543_MyMigration1’

Los archivos de migración nos permite navegar hacia adelante y hacia atrás en el estado de nuestra base de datos:

image

no los borréis salvo que ya no sea necesario mantener la posibilidad de volver a un estado anterior.

Se me han quedado algunas cosas que trataré de abordar en siguientes posts, pero espero que los conceptos básicos de como usar Migrations de forma manual y controlada hayan quedado  claros y sirvan de ayuda inicial.

He creado un pequeño modelo para que podáis hacer pruebas sin necesidad de crearos  uno por vuestra cuenta. Esta adjunto al post.

En el siguiente post veremos como exponer un modelo creado con Code First y un contexto DbContext mediante WCF Data Services 5.0.

Os recomiendo los libros de Julie Lerman sobre Code First y DbContext de la editorial O’Reilly. No deben faltar en vuestra biblioteca.