Skip to main content

Impostare un campo ID auto-increment con Entity Framework Code-First

Ho già avuto modo in un vecchio post di parlare delle potenzialità del nuovo approccio code-first introdotto da Entity Framework 6 che consente, tra le altre cose, di definire un data model completo partendo da una o più classi C# dette, per l’appunto, Entities. Una delle domande più frequenti che mi sono state fatte è quella relativa a come impostare il campo Id (o chiave primariao primary key) di una Entity in modo autoincrementale: in altre parole, come dire al Database di assegnare un identificativo numerico crescente ad ogni record.

Tanto MySQL quanto Microsoft SQL Server supportano in modo nativo colonne autoincrementali. Come fare in modo che il campo di una Entity venga definito in tal modo sul DB che andremo a generare?

La risposta è semplice: è sufficiente decorare la nostra proprietà con un apposito DatabaseGeneratedAttribute, specificando che si tratta di una identità generata automaticamente dal Database nel seguente modo:

Il campo ID sarà generato in modo autoincrementale, garantendo un ID univoco a ciascun record di tipo Item.

Felice sviluppo!

Configurare MySQL per poter utilizzare le maiuscole nei nomi delle tabelle

La configurazione predefinita delle versioni Win32 e Win64 di MySQL prevede che i nomi delle tabelle vengano convertiti in minuscolo prima di essere memorizzati su disco. Questa feature può provocare alcune scomodità a chi lavora con strumenti che generano automaticamente codice partendo dall’analisi del DB (Entity Framework, per citare uno tra i più usati), prima tra tutte l’impossibilità di avere delle classi con l’iniziale del nome in maiuscolo o in stile camelCase. Non tutti sanno che per ovviare a questo problema si può ricorrere a una variabile di sistema poco nota da inserire nel file di configurazione di MySQL che consente, per l’appunto, di determinare le modalità di memorizzazione e recupero dei nomi delle tabelle del Database.
Il comando in questione si chiama lower_case_table_names e può essere inserito nel file my.cfg , che solitamente si trova nella cartella:
C:\Program Files (x86)\MySQL\MySQL Server 5.6\
Una volta aperto è sufficiente inserire la variabile sotto la sezione [mysqld] nel seguente modo:

I valori possibili sono:

  • 0: I nomi delle tabelle e dei database vengono memorizzati rispettando le maiuscole/minuscole presenti nell’istruzione CREATE TABLE. La necessità di rispettare le maiuscole/minuscole si estende anche a tutte le query (SELECT * FROM STUDENTS e SELECT * FROM students produrranno risultati diversi in quanto cercheranno tabelle diverse). Questo valore è il predefinito delle versioni MySQL per Linux ma non è adatto per quei sistemi il cui file-system non è case-senstitive (Windows, OSX) in quanto potrebbe comportare alcuni problemi ai file degli indici.
  • 1: I nomi delle tabelle e dei database vengono convertiti in minuscolo (lowercase) prima di essere memorizzati. Questo valore è il predefinito delle versioni MySQL per Windows: il vantaggio rispetto al precedente è che consente una ricerca di tipo case-insensitive (SELECT * FROM STUDENTS e SELECT * FROM students produrranno lo stesso risultato); lo svantaggio è che non è possibile utilizzare le maiuscole, cosa che ci riporta al problema iniziale.
  • 2: I nomi delle tabelle e dei database vengono memorizzati rispettando le maiuscole/minuscole presenti nell’istruzione CREATE TABLE, ma vengono convertiti in minuscolo (lowercase) al momento di risolvere qualsiasi query di ricerca. In buona sostanza questa impostazione è un ibrido delle opzioni 0 e 1 ed è, nella maggior parte dei casi, l’opzione preferibile per i sistemi Windows e OSX in quanto consente di utilizzare le maiuscole nei nomi delle tabelle senza alcuna controindicazione a livello di ricerca.
Per una trattazione più approfondita della variabile di sistema lower_case_table_names suggeriamo di consultare la guida ufficiale di MySQL:

ASP.NET: Creare un sito web MVC5 con Database MySQL, Entity Framework 6 Code-First e Visual Studio 2013

Le nuove potenzialità di EF6 consentono di creare un sito web e relativo data model con poche righe di codice. Sul web esistono numerose guide che illustrano come fare utilizzando SQL Express, ma chi sceglie di utilizzare MySQL troverà senz’altro molto meno materiale. Questa semplice guida risponde a quanti mi hanno chiesto di riassumere i passaggi fondamentali per creare una applicazione web MVC5 configurando EF6 CF con MySQL. Per i primi passaggi mi limiterò a tradurre l’ottimo articolo Getting started with Entity Framework 6 Code First using MVC5 presente sul sito www.asp.net, dal quale prenderò anche alcune immagini a scopo divulgativo.

Questi gli strumenti di cui avremo bisogno (e relativi link alle versioni scaricabili gratuitamente):

Step 1. Creazione di una Web Application

Apriamo Visual Studio 2013 e creiamo un nuovo progetto C# in questo modo:

NP

Nella schermata successiva selezioniamo il template MVC, quindi clicchiamo sul bottone Change Authentication… per decidere se abilitare o meno l’autenticazione utente a seconda delle necessità del sito che vogliamo creare. Nell’esempio che vogliamo fare non ne abbiamo bisogno, quindi possiamo scegliere No Authentication.

CA

Completiamo quindi i passaggi necessari per ultimare la creazione del sito.

Step 2. Installazione di Entity Framework 6

Dal menu Tools (Strumenti, se avete la versione in italiano) selezioniamo Library Package Manager e poi Package Manager Console. Nella console che si aprirà digitiamo il comando seguente:

NuGet si occuperà di installare la versione più recente di Entity Framework (al momento è la 6.1.1). Una volta fatto questo possiamo cominciare a creare le nostre Entities seguendo l’approccio code-first.

Step 3. Creazione delle Entities

Una Entity non è altro che una classe pensata per contenere tutte le informazioni relative a un singolo elemento del nostro Database: prima di creare una o più Entities è quindi necessario avere una idea piuttosto chiara degli elementi di cui avremo bisogno e delle relazioni tra gli stessi che andremo ad impostare. Prendiamo come esempio il più classico degli archivi:

  • un elenco di studenti (Student)
  • che effettuano una o più iscrizioni (Enrollment)
  • a un elenco di corsi (Course).

Spostiamoci quindi all’interno della directory /Models/ (creandola se non esiste) e creiamo le seguenti tre classi:

Step 4. Creazione del Database Context

La classe principale che si occupa di tenere insieme le funzionalità dell’Entity Framework è nota come Database Context. Per crearla è sufficiente estendere la classe di sistema System.Data.Entity.DbContext specificando le Entities da includere nel Data Model. Creiamo quindi una cartella /DAL/ (che sta per Data Access Layer) e aggiungiamo le due classi seguenti:

 

Come si può vedere la classe MyDbContext.cs contiene un DbSet per ogni Entity creata in precedenza. Questo perché, secondo quanto previsto da Entity Framework, a ciascun DbSet corrisponderà una Tabella del nostro Database: le Entities, ovviamente, rappresenteranno le singole righe. Notiamo anche che nel costruttore viene impostato un oggetto di tipo MyDbInitializer, specificato nella classe successiva, che serve a creare il database nel caso in cui non esista e ad inserire tre record di esempio nella tabella Student che verrà creata. E’ possibile derivare il MyDbInitializer da numerose possibili classi di inizializzazione predefinite, come ad esempio:

  1. CreateDatabaseIfNotExists: E’ l’initializer predefinito: come suggerisce il nome, crea il database se questo non esiste: nel caso in cui il modello venga cambiato in modo da non coincidere più con il database esistente questo inizialier lancerà una eccezione. Questo comportamento lo rende ideale per gli ambienti di produzione, meno per gli ambienti di sviluppo dove il Database Model cambia di frequente.
  2. DropCreateDatabaseIfModelChanges: Questo initializer crea un nuovo database, eliminando quello eventualmente già esistente, se una o più classi relative alle Entities risultano modificate rispetto all’ultima inizializzazione. Questo comportamento lo rende ideale per gli ambienti di sviluppo, dove non è solitamente importante mantenere i dati nel DB: è sconsigliato per gli ambienti di produzione in quanto il rischio di data loss è elevato (basta un minimo aggiornamento a una classe Entity per perdere tutto l’archivio).
  3. DropCreateDatabaseAlways: Come suggerisce il nome, questo initializer elimina e ricrea il database ad ogni inizializzazione, ovvero ad ogni avvio dell’applicazione web. Il suo comportamento lo rende ideale per quegli ambienti di sviluppo che necessitano di un refresh continuo dei dati nel database: è ovviamente sconsigliato per gli ambienti di produzione.

IMPORTANTE: come si evince da questo commento, sembra che alcune versioni di Entity Framework richiedano l’utilizzo dell’inizializer DropCreateDatabaseAlways invece di CreateDatabaseIfNotExists quando il metodo sopra descritto viene utilizzato per inizializzare le Migration per la prima volta: in caso contrario, la tabella  _MigrationHistory non verrà creata e alcune cose non funzioneranno, come ad esempio il metodo Seed(). Una volta inizializzate le Migration, sarà possibile passare a un initializer diverso (CreateDatabaseIfNotExistsDropCreateDatabaseIfModelChanges) senza alcun problema.

Notiamo infine che il costruttore della nostra classe contiene un riferimento a una MyDbContextConnectionString che avremo cura di definire nel nostro Web.Config nel corso del prossimo step.

 

Step 5. Collegamento con MySQL

Per collegare la nostra web application al database MySQ abbiamo bisogno del MySQL Connector.NET, scaricabile gratuitamente dal sito web ufficiale oppure tramite NuGet. Una volta collegate le librerie al progetto avremo cura di aggiungere al Web.Config della nostra applicazione una stringa di connessione valida, completa di username e password, in questo modo:

 

Step 6. Avvio dell’applicazione e creazione del Database

Se tutti i passaggi sono stati eseguiti correttamente, l’applicazione provvederà a creare automaticamente il database non appena verrà istanziato un oggetto di tipo MyDbContext.

Questo tipo di inizializzazione può avvenire all’interno di un qualsiasi Controller oppure nel Global.asax sotto forma di proprietà statica centralizzata o in qualsiasi altro punto dell’applicazione, a seconda delle necessità dello sviluppatore e/o del design pattern e/o di eventuali strategie di IoC / UoW adottate. Nel corso di articoli successivi provvederò a fornire esempi più su queste tecniche, sull’utilizzo delle Data Migrations e sulle molte altre potenzialità dell’Entity Framework.

Close