Convenzioni Code First

Code First consente di descrivere un modello usando classi C# o Visual Basic .NET. La forma di base del modello viene rilevata usando le convenzioni. Le convenzioni sono set di regole usate per configurare automaticamente un modello concettuale basato sulle definizioni di classe quando si lavora con Code First. Le convenzioni vengono definite nello spazio dei nomi System.Data.Entity.ModelConfiguration.Conventions.

È possibile configurare ulteriormente il modello usando le annotazioni dei dati o l'API Fluent. La precedenza viene assegnata alla configurazione tramite l'API Fluent seguita da annotazioni di dati e quindi convenzioni. Per altre informazioni, vedere Annotazioni dei dati, API Fluent - Relazioni, API Fluent - Tipi e proprietà e API Fluent con VB.NET.

Un elenco dettagliato delle convenzioni Code First è disponibile nella documentazione dell'API. In questo argomento viene fornita una panoramica delle convenzioni usate da Code First.

Individuazione dei tipi

Quando si usa lo sviluppo Code First, in genere si inizia scrivendo classi .NET Framework che definiscono il modello concettuale (dominio). Oltre a definire le classi, è anche necessario comunicare a DbContext quali tipi includere nel modello. A tale scopo, si definisce una classe di contesto che deriva da DbContext ed espone le proprietà DbSet per i tipi che si desidera far parte del modello. Code First includerà questi tipi e eseguirà anche il pull di qualsiasi tipo a cui si fa riferimento, anche se i tipi a cui si fa riferimento sono definiti in un assembly diverso.

Se i tipi partecipano a una gerarchia di ereditarietà, è sufficiente definire una proprietà DbSet per la classe base e i tipi derivati verranno inclusi automaticamente, se si trovano nello stesso assembly della classe base.

Nell'esempio seguente è presente una sola proprietà DbSet definita nella classe SchoolEntities (Reparti). Code First usa questa proprietà per individuare ed eseguire il pull di qualsiasi tipo a cui si fa riferimento.

public class SchoolEntities : DbContext
{
    public DbSet<Department> Departments { get; set; }
}

public class Department
{
    // Primary key
    public int DepartmentID { get; set; }
    public string Name { get; set; }

    // Navigation property
    public virtual ICollection<Course> Courses { get; set; }
}

public class Course
{
    // Primary key
    public int CourseID { get; set; }

    public string Title { get; set; }
    public int Credits { get; set; }

    // Foreign key
    public int DepartmentID { get; set; }

    // Navigation properties
    public virtual Department Department { get; set; }
}

public partial class OnlineCourse : Course
{
    public string URL { get; set; }
}

public partial class OnsiteCourse : Course
{
    public string Location { get; set; }
    public string Days { get; set; }
    public System.DateTime Time { get; set; }
}

Se si vuole escludere un tipo dal modello, usare l'attributo NotMapped o l'API DbModelBuilder.Ignore fluent.

modelBuilder.Ignore<Department>();

Convenzione chiave primaria

Code First deduce che una proprietà è una chiave primaria se una proprietà di una classe è denominata "ID" (senza distinzione tra maiuscole e minuscole) o il nome della classe seguito da "ID". Se il tipo della proprietà della chiave primaria è numerico o GUID, verrà configurato come colonna Identity.

public class Department
{
    // Primary key
    public int DepartmentID { get; set; }

    . . .  

}

Convenzione di relazione

In Entity Framework le proprietà di spostamento consentono di spostarsi tra due tipi di entità per spostarsi tra due tipi di entità. Ogni oggetto può disporre di una proprietà di navigazione per ogni relazione di cui fa parte. Le proprietà di navigazione consentono di spostarsi e gestire le relazioni in entrambe le direzioni, restituendo un oggetto riferimento (se la molteplicità è una o zero-o-uno) o una raccolta (se la molteplicità è molti). Code First deduce le relazioni in base alle proprietà di navigazione definite nei tipi.

Oltre alle proprietà di navigazione, è consigliabile includere proprietà di chiave esterna sui tipi che rappresentano oggetti dipendenti. Qualsiasi proprietà con lo stesso tipo di dati della proprietà della chiave primaria principale e con un nome che segue uno dei formati seguenti rappresenta una chiave esterna per la relazione: '<nome della proprietà del nome della proprietà principale della chiave primaria nome> della proprietà della chiave primaria del nome><della proprietà della classe principale',<>>< o '<nome> della proprietà chiave primaria principale principale'. Se vengono trovate più corrispondenze, la precedenza viene assegnata nell'ordine indicato in precedenza. Il rilevamento delle chiavi esterne non fa distinzione tra maiuscole e minuscole. Quando viene rilevata una proprietà di chiave esterna, Code First deduce la molteplicità della relazione in base al supporto dei valori Null della chiave esterna. Se la proprietà è nullable, la relazione viene registrata come facoltativa; in caso contrario, la relazione viene registrata come richiesto.

Se una chiave esterna nell'entità dipendente non è nullable, Code First imposta l'eliminazione a catena sulla relazione. Se una chiave esterna nell'entità dipendente è nullable, Code First non imposta l'eliminazione a catena sulla relazione e quando l'entità viene eliminata la chiave esterna verrà impostata su Null. Il comportamento di eliminazione a catena e molteplicità rilevato per convenzione può essere sottoposto a override usando l'API Fluent.

Nell'esempio seguente vengono usate le proprietà di navigazione e una chiave esterna per definire la relazione tra le classi Department e Course.

public class Department
{
    // Primary key
    public int DepartmentID { get; set; }
    public string Name { get; set; }

    // Navigation property
    public virtual ICollection<Course> Courses { get; set; }
}

public class Course
{
    // Primary key
    public int CourseID { get; set; }

    public string Title { get; set; }
    public int Credits { get; set; }

    // Foreign key
    public int DepartmentID { get; set; }

    // Navigation properties
    public virtual Department Department { get; set; }
}

Nota

Se si hanno più relazioni tra gli stessi tipi (ad esempio, si supponga di definire le classi Person e Book, in cui la classe Person contiene le proprietà di navigazione ReviewedBooks e AuthoredBooks e la classe Book contiene le proprietà di navigazione Autore e Revisore) è necessario configurare manualmente le relazioni usando annotazioni dati o l'API Fluent. Per altre informazioni, vedere Annotazioni dei dati - Relazioni e API Fluent - Relazioni.

Convenzione dei tipi complessi

Quando Code First individua una definizione di classe in cui non è possibile dedurre una chiave primaria e non viene registrata alcuna chiave primaria tramite annotazioni di dati o l'API Fluent, il tipo viene registrato automaticamente come tipo complesso. Per il rilevamento dei tipi complessi è inoltre necessario che il tipo non abbia proprietà che fanno riferimento ai tipi di entità e non faccia riferimento a una proprietà della raccolta in un altro tipo. Dato che le definizioni di classe seguenti Code First dedurrebbero che Details è un tipo complesso perché non ha una chiave primaria.

public partial class OnsiteCourse : Course
{
    public OnsiteCourse()
    {
        Details = new Details();
    }

    public Details Details { get; set; }
}

public class Details
{
    public System.DateTime Time { get; set; }
    public string Location { get; set; }
    public string Days { get; set; }
}

Convenzione stringa di Connessione ion

Per informazioni sulle convenzioni usate da DbContext per individuare la connessione da usare, vedere Connessione ions e modelli.

Rimozione di convenzioni

È possibile rimuovere qualsiasi convenzione definita nello spazio dei nomi System.Data.Entity.ModelConfiguration.Conventions. Nell'esempio seguente viene rimosso PluralizingTableNameConvention.

public class SchoolEntities : DbContext
{
     . . .

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // Configure Code First to ignore PluralizingTableName convention
        // If you keep this convention, the generated tables  
        // will have pluralized names.
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }
}

Convenzioni personalizzate

Le convenzioni personalizzate sono supportate in EF6 e versioni successive. Per altre informazioni, vedere Convenzioni code first personalizzate.