Entity Framework
Code First - Fluent API
Recherche…
Remarques
Il existe deux manières générales de spécifier HOW Entity Framework qui mappera les classes POCO aux tables de base de données, aux colonnes, etc.: Annotations de données et API Fluent .
Bien que les annotations de données soient simples à lire et à comprendre, elles manquent de certaines fonctionnalités, telles que la spécification du comportement "Cascade on Delete" pour une entité. D'autre part, l'API Fluent est un peu plus complexe à utiliser, mais fournit un ensemble de fonctionnalités beaucoup plus avancé.
Modèles de cartographie
EntityFramewok Fluent API est un moyen puissant et élégant de mapper vos modèles de domaine en code premier sur une base de données sous-jacente. Cela peut également être utilisé avec code-first avec la base de données existante . Vous avez deux options lorsque vous utilisez l' API Fluent : vous pouvez mapper directement vos modèles sur la méthode OnModelCreating ou vous pouvez créer des classes de mappeur qui héritent de EntityTypeConfiguration , puis ajouter ces modèles à modelBuilder sur la méthode OnModelCreating . La deuxième option est celle que je préfère et je vais vous en donner un exemple.
Première étape: Créer un modèle
public class Employee
{
public int Id { get; set; }
public string Surname { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public short Age { get; set; }
public decimal MonthlySalary { get; set; }
public string FullName
{
get
{
return $"{Surname} {FirstName} {LastName}";
}
}
}
Etape 2: Créer une classe de mappeur
public class EmployeeMap
: EntityTypeConfiguration<Employee>
{
public EmployeeMap()
{
// Primary key
this.HasKey(m => m.Id);
this.Property(m => m.Id)
.HasColumnType("int")
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
// Properties
this.Property(m => m.Surname)
.HasMaxLength(50);
this.Property(m => m.FirstName)
.IsRequired()
.HasMaxLength(50);
this.Property(m => m.LastName)
.HasMaxLength(50);
this.Property(m => m.Age)
.HasColumnType("smallint");
this.Property(m => m.MonthlySalary)
.HasColumnType("number")
.HasPrecision(14, 5);
this.Ignore(m => m.FullName);
// Table & column mappings
this.ToTable("TABLE_NAME", "SCHEMA_NAME");
this.Property(m => m.Id).HasColumnName("ID");
this.Property(m => m.Surname).HasColumnName("SURNAME");
this.Property(m => m.FirstName).HasColumnName("FIRST_NAME");
this.Property(m => m.LastName).HasColumnName("LAST_NAME");
this.Property(m => m.Age).HasColumnName("AGE");
this.Property(m => m.MonthlySalary).HasColumnName("MONTHLY_SALARY");
}
}
Expliquons les cartographies:
- HasKey - définit la clé primaire. Les clés primaires composites peuvent également être utilisées. Par exemple: this.HasKey (m => new {m.DepartmentId, m.PositionId}) .
- Propriété - permet de configurer les propriétés du modèle.
- HasColumnType - spécifie le type de colonne de niveau base de données. Veuillez noter que cela peut être différent pour différentes bases de données comme Oracle et MS SQL.
- HasDatabaseGeneratedOption - spécifie si la propriété est calculée au niveau de la base de données. Les PK numériques sont DatabaseGeneratedOption.Identity par défaut, vous devez spécifier DatabaseGeneratedOption.None si vous ne le souhaitez pas.
- HasMaxLength - limite la longueur de la chaîne.
- IsRequired - marque la propriété comme requis.
- HasPrecision - nous permet de spécifier la précision pour les décimales.
- Ignorer - Ignore complètement la propriété et ne la mappe pas à la base de données. Nous avons ignoré FullName, car nous ne voulons pas que cette colonne figure dans notre table.
- ToTable - spécifiez le nom de la table et le nom du schéma (facultatif) pour le modèle.
- HasColumnName - relie la propriété au nom de la colonne. Cela n'est pas nécessaire lorsque les noms de propriété et les noms de colonne sont identiques.
Troisième étape: Ajouter une classe de mappage aux configurations.
Nous devons dire à EntityFramework d'utiliser notre classe de mappeur. Pour ce faire, nous devons l’ajouter à modelBuilder.Configurations sur la méthode OnModelCreating :
public class DbContext()
: base("Name=DbContext")
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new EmployeeMap());
}
}
Et c'est tout. Nous sommes tous prêts à partir.
Clé primaire
En utilisant la méthode .HasKey (), une propriété peut être explicitement configurée en tant que clé primaire de l'entité.
using System.Data.Entity;
// ..
public class PersonContext : DbContext
{
// ..
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// ..
modelBuilder.Entity<Person>().HasKey(p => p.PersonKey);
}
}
Clé primaire composite
En utilisant la méthode .HasKey (), un ensemble de propriétés peut être explicitement configuré en tant que clé primaire composite de l'entité.
using System.Data.Entity;
// ..
public class PersonContext : DbContext
{
// ..
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// ..
modelBuilder.Entity<Person>().HasKey(p => new { p.FirstName, p.LastName });
}
}
Longueur maximale
En utilisant la méthode .HasMaxLength (), le nombre maximal de caractères peut être configuré pour une propriété.
using System.Data.Entity;
// ..
public class PersonContext : DbContext
{
// ..
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// ..
modelBuilder.Entity<Person>()
.Property(t => t.Name)
.HasMaxLength(100);
}
}
La colonne résultante avec la longueur de colonne spécifiée:
Propriétés requises (NOT NULL)
En utilisant la méthode .IsRequired (), les propriétés peuvent être spécifiées comme obligatoires, ce qui signifie que la colonne aura une contrainte NOT NULL.
using System.Data.Entity;
// ..
public class PersonContext : DbContext
{
// ..
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// ..
modelBuilder.Entity<Person>()
.Property(t => t.Name)
.IsRequired();
}
}
La colonne résultante avec la contrainte NOT NULL:
Expliquer la dénomination de la clé étrangère
Lorsqu'une propriété de navigation existe sur un modèle, Entity Framework crée automatiquement une colonne de clé étrangère. Si un nom de clé étrangère spécifique est souhaité, mais qu'il ne figure pas en tant que propriété dans le modèle, il peut être défini explicitement à l'aide de l'API Fluent. En utilisant la méthode Map
lors de l'établissement de la relation avec la clé étrangère, tout nom unique peut être utilisé pour les clés étrangères.
public class Company
{
public int Id { get; set; }
}
public class Employee
{
property int Id { get; set; }
property Company Employer { get; set; }
}
public class EmployeeContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>()
.HasRequired(x => x.Employer)
.WithRequiredDependent()
.Map(m => m.MapKey("EmployerId"));
}
}
Après avoir spécifié la relation, la méthode Map
permet de définir explicitement le nom de la clé étrangère en exécutant MapKey
. Dans cet exemple, ce qui aurait abouti à un nom de colonne de Employer_Id est désormais EmployerId.