Parte 2: Creazione di modelli di dominio

di Rick Anderson

Scaricare il progetto completato

Aggiungere modelli

Esistono tre modi per approcciare Entity Framework:

  • Database-first: si inizia con un database e Entity Framework genera il codice.
  • Model-first: si inizia con un modello visivo e Entity Framework genera sia il database che il codice.
  • Code-first: si inizia con il codice e Entity Framework genera il database.

Viene usato l'approccio code-first, quindi si inizia definendo gli oggetti di dominio come poCO (oggetti CLR precedenti). Con l'approccio code-first, gli oggetti di dominio non necessitano di codice aggiuntivo per supportare il livello di database, ad esempio transazioni o persistenza. In particolare, non è necessario ereditare dalla classe EntityObject . È comunque possibile usare le annotazioni dei dati per controllare la modalità di creazione dello schema del database da parte di Entity Framework.

Poiché i POCO non contengono proprietà aggiuntive che descrivono lo stato del database, possono essere facilmente serializzate in JSON o XML. Tuttavia, ciò non significa che è sempre necessario esporre i modelli di Entity Framework direttamente ai client, come si vedrà più avanti nell'esercitazione.

Verranno creati i poCO seguenti:

  • Prodotto
  • Ordine
  • OrderDetail

Per creare ogni classe, fare clic con il pulsante destro del mouse sulla cartella Models in Esplora soluzioni. Dal menu di scelta rapida selezionare Aggiungi e quindi Selezionare Classe.

Screenshot del menu Esplora soluzioni per la cartella Modelli. Il menu Aggiungi è aperto e l'opzione Classe è evidenziata.

Aggiungere una Product classe con l'implementazione seguente:

namespace ProductStore.Models
{
    using System.ComponentModel.DataAnnotations;

    public class Product
    {
        [ScaffoldColumn(false)]
        public int Id { get; set; }
        [Required]
        public string Name { get; set; }
        public decimal Price { get; set; }
        public decimal ActualCost { get; set; }
    }
}

Per convenzione, Entity Framework usa la Id proprietà come chiave primaria ed esegue il mapping a una colonna Identity nella tabella di database. Quando si crea una nuova Product istanza, non si imposterà un valore per Id, perché il database genera il valore .

L'attributo ScaffoldColumn indica ASP.NET MVC di ignorare la proprietà durante la Id generazione di un modulo dell'editor. L'attributo Required viene usato per convalidare il modello. Specifica che la Name proprietà deve essere una stringa non vuota.

Aggiungere la Order classe :

namespace ProductStore.Models
{
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;

    public class Order
    {
        public int Id { get; set; }
        [Required]
        public string Customer { get; set; }

        // Navigation property
        public  ICollection<OrderDetail> OrderDetails { get; set; }
    }
}

Aggiungere la OrderDetail classe :

namespace ProductStore.Models
{
    public class OrderDetail
    {
        public int Id { get; set; }
        public int Quantity { get; set; }
        public int OrderId { get; set; }
        public int ProductId { get; set; }

        // Navigation properties
        public Product Product { get; set; }
        public Order Order { get; set; }
    }
}

Relazioni chiave esterna

Un ordine contiene molti dettagli dell'ordine e ogni dettaglio dell'ordine fa riferimento a un singolo prodotto. Per rappresentare queste relazioni, la OrderDetail classe definisce le proprietà denominate OrderId e ProductId. Entity Framework dedurrà che queste proprietà rappresentano chiavi esterne e aggiungeranno vincoli di chiave esterna al database.

Screenshot dei menu di Visual Studio per le classi Orders, Products e OrderDetails.

Le Order classi e OrderDetail includono anche le proprietà di "navigazione", che contengono riferimenti agli oggetti correlati. Dato un ordine, è possibile passare ai prodotti nell'ordine seguendo le proprietà di navigazione.

Compilare ora il progetto. Entity Framework usa la reflection per individuare le proprietà dei modelli, quindi richiede un assembly compilato per creare lo schema del database.

Configurare i formattatori di Media-Type

Un formattatore di tipo multimediale è un oggetto che serializza i dati quando l'API Web scrive il corpo della risposta HTTP. I formattatori predefiniti supportano l'output JSON e XML. Per impostazione predefinita, entrambi questi formattatori serializzano tutti gli oggetti in base al valore.

La serializzazione per valore crea un problema se un oggetto grafico contiene riferimenti circolari. Questo è esattamente il caso delle Order classi e OrderDetail , perché ognuno contiene un riferimento all'altro. Il formattatore seguirà i riferimenti, scriverà ogni oggetto per valore e passerà in cerchi. È quindi necessario modificare il comportamento predefinito.

In Esplora soluzioni espandere la cartella App_Start e aprire il file denominato WebApiConfig.cs. Aggiungere il codice seguente alla classe WebApiConfig:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        // New code:
        var json = config.Formatters.JsonFormatter;
        json.SerializerSettings.PreserveReferencesHandling =
            Newtonsoft.Json.PreserveReferencesHandling.Objects;

        config.Formatters.Remove(config.Formatters.XmlFormatter);
    }
}

Questo codice imposta il formattatore JSON per mantenere i riferimenti agli oggetti e rimuove completamente il formattatore XML dalla pipeline. È possibile configurare il formattatore XML per mantenere i riferimenti agli oggetti, ma è un po' più funzionante e per questa applicazione è necessario solo JSON. Per altre informazioni, vedere Gestione di riferimenti a oggetti circolari.