in ASPNET Core

Owned Types in Entity Framework Core

Entity Framework Core consente di definire una particolare tipologia di proprietà chiamate Owned Types. Già presenti all’interno di Entity Framework sotto il nome di Complex Types, sono stati reintrodotti all’interno di Entity Framework Core a partire dalla versione 2.0. Questa funzionalità non era stata riportata in Entity Framework Core 1.0.

L’obiettivo di questa tipologia di dati è quella di evitare il dover ripetere la definizione delle proprietà comuni nella definizione delle entity.

Supponendo di aver definito un’entity Person nel modo seguente: 

public class Person
{
   public int BusinessEntityID { get; set; }
   public string FirstName { get; set; }
   public string MiddleName { get; set; }
   public string LastName { get; set; }
}

è possibile raggruppare alcuni campi mediante una classe, referenziata come proprietà:

public class Person
{
   public int BusinessEntityID { get; set; }
   public Name Name {get;set;}
}

//owned type
public class Name 
{
   public string FirstName { get; set; }
   public string MiddleName { get; set; }
   public string LastName { get; set; }
}

Praticamente, è stata creata una nuova proprietà Name, composto da tre proprietà riutilizzabili nella definizione di altre entity.

A questo punto è necessario procedere con la mappatura all’interno dell’entity Person per poter utilizzare l’owned type Name.  La mappatura viene effettuata all’interno del metodo OnModelCreating del context: 

OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity().OwnsOne(e => e.Name).Property(e => e.FirstName).HasColumnName("FirstName");
    modelBuilder.Entity().OwnsOne(e => e.Name).Property(e => e.MiddleName).HasColumnName("MiddleName");
    modelBuilder.Entity().OwnsOne(e => e.Name).Property(e => e.LastName).HasColumnName("LastName");
}

E’ da notare la presenza del metodo OwnsOne(…) che sta a specificare la mappatura con l’owned type, seguito dai soliti metodi utilizzati per le entity Property e HasColumnName: 

  • PropertyName:  specifica il nome della proprietà
  • HasColumnName: specifica il nome dell colonna della tabella 

Per convenzione Entity Framework effettua la mappatura verso la tabella seguendo la convenzione EntityProperty_OwnedEntityProperty, ecco perchè è necessario indicare le due proprietà precedenti per customizzarne la mappatura.

Il risultato sarà la mappatura verso una tabella denominata Person che conterrà i campi definiti all’interno della classe Person e i campi presenti all’interno della proprietà di tipo Name.  Ad esempio, recuperando i dati della tabella Person tramite una query Select di Linq il risultato sarà quello di avere i campi della proprietà Name valorizzati automaticamente: 

owned types

A partire da Entity Framework Core 2.1 è inoltre possibile utilizzare la data annotation [Owned] :

public class Person
{
   public int BusinessEntityID { get; set; }
   public Name Name {get;set;}
}

[Owned]
public class Name 
{
   public string FirstName { get; set; }
   public string MiddleName { get; set; }
   public string LastName { get; set; }
}

Il framework consente anche di mappare gli owned types all’interno di una tabella specifica (e separata) utilizzando il metodo ToTable(…):

modelBuilder.Entity<Person>().OwnsOne(p => p.Name, od =>
    {
        od.OwnsOne(c => c.FirstName);
        od.OwnsOne(c => c.MiddleName);
        od.OwnsOne(c => c.LastName);
        od.ToTable("NameTable");
    });