Nei tutorial di Entity Framework e Web Api abbiamo visto cosa sono queste tecnologie e come realizzare le nostre applicazioni sfruttando i concetti base, perciò ora proviamo a esercitarci un po’.

Immaginiamo di voler realizzare una applicazione web per la gestione degli eventi di una scuola italiana, per prima cosa creiamo un nuovo progetto, come spiegato qui e otteniamo il seguente risultato:

image

poi decidiamo le funzionalità principali dell’applicazione, ossia cosa dovrebbe fare, ad esempio:

  1. dovrebbe essere aperta solo agli studenti della scuola, perciò dovrebbe permettere la registrazione al sistema;
  2. dovrebbe permettere l’inserimento, la modifica e la cancellazione degli eventi agli studenti che sono anche amministratori del sistema;
  3. dovrebbe permettere a tutti gli studenti registrati (amministratori e non), di prenotare la partecipazione all’evento e ovviamente anche di cancellarla.

A questo punto iniziamo ad esaminare le classi da inserire nell’applicazione, sicuramente abbiamo bisogno di una classe:

  • Evento”, in cui inserire tutti i dati dell’evento (identificativo univoco, nome dell’evento, descrizione, numero massimo di partecipanti, data e ora d’inizio e data e ora di fine, etc.),
  • Utente”, in cui memorizzare tutti i dati degli studenti registrati a sistema e che quindi possono accedere all’applicazione web (identificativo univoco, username, password, nome, cognome, email, tipo di utente, etc.)
  • Location”, in cui memorizzare tutte le informazioni dei luoghi che possono essere utilizzati per organizzare gli eventi (identificativo univoco, nome, descrizione, capienza massima, indirizzo etc.)
  • Registrazione”, in cui memorizzare la registrazione di uno studente all’evento, e la sua effettiva partecipazione (identificativo univoco, id dell’evento, id dell’utente, data di registrazione, stato registrazione, data partecipazione, etc.)

Adesso realizziamo le nostre classi, cominciamo da “Location”, però prima raggruppiamo tutte le informazioni riguardanti l’indirizzo in una classe, che chiameremo “Indirizzo”, per rendere più leggibile e semplice il codice. A questa classe Indirizzo, Entity Framework non dovrà associare alcuna tabella, ossia tutte le proprietà di questa classe, dovranno essere presenti nella tabella Location. Iniziamo, posizioniamoci sulla cartella “Models” e selezioniamo Aggiungi Classe (tasto destro del mouse)

image

la chiamiamo “Indirizzo“ e clicchiamo su Aggiungi

image

ora nella finestra che si apre, scriviamo il nostro codice:

    public class Indirizzo
    {
        public string Via { get; set; }
        public string NumeroCivico { get; set; }
        public string Citta { get; set; }
        public string Provincia { get; set; }
        public string Cap { get; set; }
    }

image

infine salviamo. Ora aggiungiamo la classe “Location” (come prima Models => Aggiungi Classe)

image

e utilizziamo le Convention e le DataAnnotation di Entity Framework (viste nei tutorial) per decidere come sarà la tabella del database che dovrà essere creata.

Innanzitutto decidiamo il nome della tabella (“Locations”) e utilizziamo la parola chiave Table per comunicarlo ad EF; mentre scriviamo ci compare una lampadina, clicchiamo sulla voce “using System.ComponentModel.DataAnnotations.Schema”, per aggiungere quella classe alla nostra e correggere l’errore evidenziato da Visual Studio

Screen Shot 11-10-15 at 10.57 AMimage

poi scriviamo tutte le proprietà che ci servono: “Id”, “Nome”, “Descrizione”, “Capienza”, “Indirizzo”

Nota: per scrivere velocemente una proprietà si può scrivere “prop” e poi premere il tasto “Tab” 

    [Table("Locations")]
    public class Location
    {        
        public int Id { get; set; }               
        public string Nome { get; set; }
        public string Descrizione { get; set; }
        public int Capienza { get; set; }                
        public Indirizzo Indirizzo { get; set; }
    }

Ora aggiungiamo le parole chiave Key, MaxLength e Required per indicare a EF quale proprietà sarà la chiave primaria e quale sarà la loro lunghezza massima, anche in questo caso mentre scriviamo ci compare una lampadina, clicchiamo sulla voce “using System.ComponentModel.DataAnnotations”, per aggiungere quella classe alla nostra e correggere l’errore evidenziato da Visual Studio

image

    [Table("Locations")]
    public class Location
    {
        public Location()
        {
            Indirizzo = new Indirizzo();
        }

        [Key]
        public int IdLocation { get; set; }

        [MaxLength(250)]
        [Required(ErrorMessage = "Inserire un nome per la location")]
        public string Nome { get; set; }
                
        public string Descrizione { get; set; }

        public int Capienza { get; set; }
                
        public Indirizzo Indirizzo { get; set; }
    }
image

Prima di andare avanti alcuni piccoli chiarimenti:

  • la parola chiave Key, indica che proprietà sarà la chiave primaria della tabella, se avessimo scritto ID, EF grazie alla Primary Convention avrebbe capito da solo, che quella proprietà doveva essere la chiave primaria della tabella
  • la parola chiave “Required”, indica che il campo è obbligatorio, nel database e nell’interfaccia grafica, che creeremo per inserire i relativi valori, mentre la parola chiave “ErrorMessage” indica il messaggio da restituire all’utente, nell’interfaccia grafica.
  • la proprietà indirizzo di tipo “Indirizzo” serve per comunicare ad EF, che tutte le proprietà della classe Indirizzo dovranno essere aggiunte alla tabella “Locations”.
  • utilizziamo il costruttore Location() per inizializzare la proprietà Indirizzo

A questo punto aggiungiamo le classi “Evento” e “Registrazione”, ripetendo le operazioni già effettuate prima:

[Table("Registrazioni")] public class Registrazione { public int ID { get; set; }
public DateTime DataRichiestaRegistrazione { get; set; } public DateTime DataConfermaRegistrazione { get; set; } public DateTime DataUltimoStato { get; set; } public StatoRegistrazione StatoRegistrazione { get; set; } public DateTime DataPartecipazione { get; set; } public string Nota { get; set; } } public enum StatoRegistrazione { Richiesta = 1, StandBy = 2, Confermata = 3, Negata = 4, Annullata = 5 }

    [Table("Eventi")]
    public class Evento
    {
        public int ID { get; set; }

        [Required(ErrorMessage = "Inserire un nome")]
        [MaxLength(100)]
        public string Nome { get; set; }

        [Required(ErrorMessage = "Inserire una descrizione")]
        public string Descrizione { get; set; }

        [Column("DescBreve")]
        [Display(Name = "Descrizione Breve")]
        [MaxLength(500)]
        public string DescrizioneBreve { get; set; }

        [Required]
        [Display(Name = "Numero Posti")]
        public int NumeroPosti { get; set; }

        [DataType(DataType.ImageUrl, ErrorMessage = "Inserire un url valido")]
        [MaxLength(250)]
        [Display(Name = "Url Evento")]
        public string UrlEvento { get; set; }

        [DataType(DataType.ImageUrl, ErrorMessage = "Inserire un url valido")]
        [MaxLength(250)]
        [Display(Name = "Url Immagine")]
        public string UrlImmagine { get; set; }

        [DataType(DataType.DateTime)]
        [Display(Name = "Data Inizio")]
        public DateTime Inizio { get; set; }

        [DataType(DataType.DateTime)]
        [Display(Name = "Data Fine")]
        public DateTime Fine { get; set; }

        public int LocationID { get; set; }
        [ForeignKey("LocationID")]
        public virtual Location Location { get; set; }

        
    }

Analizziamo quanto abbiamo scritto, prima di tutto abbiamo utilizzato due parole chiavi nuove:

  • Column, che indica il nome che EF dovrà dare alla relativa colonna del database
  • e DataType, che indica il tipo di dato che EF dovrà assegnare alla relativa colonna del database

poi abbiamo sfruttato:

  • la Primary Key Convention per le chiavi primarie, chiamando le proprietà ID
  • e la Foreign Key Convention in accoppiata con la Foreign Key DataAnnotation per la chiave esterna, in questo modo abbiamo definito esplicitamente la chiave esterna (LocationID) e l’abbiamo chiamata con un nome diverso rispetto al relativo nome della chiava primaria (classe Location nome proprietà IdLocation).

Infine cenni di programmazione:

  • la parola chiave enum serve per definire un enumeratore di valori costanti, con la relativa descrizione. Nel nostro caso ci serve per indicare che nella proprietà StatoRegistrazione saranno ammessi solo i valori da 1 a 5, che corrispondono agli stati “Richiesta”, “StandBy”, “Confermata”, “Negata”, “Annullata”.
  • la parola chiave virtual serve per indicare che la proprietà può essere modificata nelle classi che ereditano dalla classe in cui si trova la proprietà (vedere i concetti di ereditarietà e polimorfismo). Nel nostro caso serve solo per comunicare ad EF che la proprietà non deve essere riportata in tabella, ma deve essere valorizzata mediante la chiave esterna.

 

A questo punto per completare le due classi dobbiamo aggiungere le relative associazioni, in questo modo:

  • nella classe Registrazione aggiungiamo la chiave esterna che indica a quale evento si è iscritto lo studente (Relazione uno a uno):
        public int EventoID { get; set; }
        [ForeignKey("EventoID")]
        public virtual Evento Eventi { get; set; }
  • nella classe Evento invece aggiungiamo la relazione uno a molti, ossia tutti i partecipanti iscritti all’evento (o meglio la lista dei partecipanti dell’evento), in questo modo:
        public virtual ICollection<Registrazione> Partecipanti { get; set; }

 image

image

Per concludere il dominio delle classi resta da analizzare la classe Utente, ma in realtà possiamo evitare di crearla in quanto per la gestione degli utenti, con i relativi ruoli all’interno dell’applicazione (amministratore/utilizzatore), possiamo utilizzare un componente del .NET Framework, che si chiama AspNet Identity.

Questo componente si occupa di creare e gestire tutte le tabelle necessarie alla gestione degli accessi, tenendo in considerazione i principi più importanti della sicurezza nel web, c’è solo una piccola modifica da fare per aggiungere ad AspNet Identity il nome e il cognome dell’utente, in quanto non sono gestiti, vediamo come fare:

  • apriamo il file IdentityModels che si trova nella cartella Models (doppio click sul nome del file)
  • aggiungiamo le proprietà nome e cognome e salviamo (grazie a queste proprietà EF capisce che devono essere aggiunte le relative due colonna alla tabella degli utenti AspNet Identity):

image

  • poi apriamo il file AccountViewModels della cartella Models
  • e aggiungiamo alla classe RegisterBindingModel il seguente codice:
        [Required]
        [Display(Name = "Nome")]
        public string Nome { get; set; }

        [Required]
        [Display(Name = "Cognome")]
        public string Cognome { get; set; }


In seguito apriamo il file AccountController della cartella Controller e modifichiamo il metodo Register in questo modo:

        // POST api/Account/Register
        [AllowAnonymous]
        [Route("Register")]
        public async Task<IHttpActionResult> Register(RegisterBindingModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var user = new ApplicationUser() { UserName = model.Email, Email = model.Email, Cognome = model.Cognome, Nome = model.Nome  };

            IdentityResult result = await UserManager.CreateAsync(user, model.Password);

            if (!result.Succeeded)
            {
                return GetErrorResult(result);
            }

            return Ok();
        }

Le modifiche a queste due classi ci serviranno per memorizzare le informazioni riguardanti il Nome e il Cognome del nuovo utente in fase di registrazione.

Ora non ci resta che aggiungere la relazione tra Utente e Registrazione, in cui stabiliamo che ogni registrazione ad un evento deve essere associata ad un solo utente, ma ovviamente ogni utente potrà effettuare più registrazioni ad eventi diversi. Come già visto in precedenza dobbiamo aggiungere alla classe Registrazione la chiave esterna:

        public string UtenteId { get; set; }
        public virtual UtenteViewModel Utenti { get; set; }

sfruttando solo la Foreign Key Convention senza la DataAnnotation, in quanto il nome della chiave esterna (UtenteId) coincide con il nome della chiave primaria.

image

Per concludere la prima parte dell’esercitazione vediamo come aggiungere i controller alla soluzione, però prima salviamo tutto e compiliamo.

image

Nota: I controller sono classi particolari che ci permettono di gestire le azioni sulle nostre risorse, ossia sugli oggetti appartenenti al nostro dominio delle classi, e per questo motivo dobbiamo aggiungere un controller per ogni classe definita.

Iniziamo ad aggiungere il controller della classe “Location”, posizioniamoci sulla cartella “Controller” e selezioniamo Aggiungi Controller (tasto destro del mouse)

image

nella finestra che si apre selezioniamo Controller Web Api 2 con azioni, che utilizza Entity Framework e premiamo Aggiungi

image

selezioniamo la classe “Location”

image

selezioniamo il contesto in cui EF dovrà lavorare (per ora lasciamo il contesto base dell’applicazione)

image

infine controlliamo il nome assegnato di default al controller, e lo cambiamo se non ci piace, e clicchiamo su Aggiungi.

Il sistema crea la classe con i metodi base per l’utilizzo delle web api, ossia per l’utilizzo dei verbi GET, POST, PUT, e DELETE,

image

ed inoltre aggiunge nel file di contesto IdentityModels (visto prima)

la proprietà che comunica a EF che dovrà legare la classe Location alla relativa tabella Locations

public System.Data.Entity.DbSet<GestioneEventiScuola.Models.Location> Locations { get; set; }

Ripetiamo l’operazione appena fatta anche per le classi Evento, e Registrazione però cambiamo i nomi suggeriti in questo modo:

  • EventoesController => EventiController,
  • RegistrazionesController = RegistrazioniController

image image

Adesso abbiamo tutte le nostre classi e i controller che ci servono (per la gestione dell’utente utilizzeremo il controller già presente nella soluzione AccountController) :

image

Infine torniamo nel file di contesto e controlliamo i nomi delle proprietà che sono state aggiunte:

 image

cambiamo Eventoes con Eventi e clicchiamo sulla lampadina che compare, selezionando rinomina come in figura:

image

allo stesso modo cambiamo anche Registraziones con Registrazioni

image

Per sicurezza ora ritorniamo nei file EventiController e RegistrazioniController e controlliamo che le proprietà rinominate siano state corrette così:

imageimage

notiamo inoltre che i metodi Get (che restituiscono l’elenco delle risorse) sono stati chiamati per default “GetEventoes” e “GetRegistraziones”, rinominiamo anche questi in GetEventi e GetRegistrazioni, poi salviamo tutto e compiliamo.

imageimage

Concludiamo la prima parte dell’esercitazione lanciando l’applicazione (CTRL + F5 o semplicemente F5)

image

e controllando, mediante il link API, che siano presenti le nostre risorse: “Locations”, “Eventi” e “Registrazioni”.

image

Nella seconda parte dell’esercitazione vedremo come inserire i dati nel database, verificando che EF crei tutto correttamente.

Autore:


blog comments powered by Disqus