Créer des entités
Notions théoriques
Qu'est-ce qu'une entité ?
Une entité est une classe C# qui représente une table en base de données. Chaque instance de la classe correspond à une ligne (enregistrement) de la table.
// Models/Article.cs
public class Article
{
public int Id { get; set; } // → colonne id (clé primaire)
public string Titre { get; set; } // → colonne Titre (varchar)
public string Contenu { get; set; } // → colonne Contenu (text)
public DateTime DateCreation { get; set; } // → colonne DateCreation
}
EF Core mappe automatiquement les propriétés C# aux colonnes SQL par convention.
Les DataAnnotations
Les DataAnnotations sont des attributs C# (entre [...]) qui permettent de configurer le mapping et la validation :
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
public class Article
{
[Key] // Clé primaire (convention : propriété Id)
public int Id { get; set; }
[Required] // NOT NULL en base + validation formulaire
[MaxLength(200)] // VARCHAR(200) en base
public string Titre { get; set; } = string.Empty;
[Required]
public string Contenu { get; set; } = string.Empty;
[Column("date_creation")] // Nom de colonne personnalisé en base
public DateTime DateCreation { get; set; } = DateTime.UtcNow;
[NotMapped] // Propriété ignorée par EF Core (pas de colonne)
public string ResumeCourt => Contenu.Length > 100
? Contenu.Substring(0, 100) + "..."
: Contenu;
}
// Doctrine (Symfony) : annotations PHP
#[ORM\Entity]
#[ORM\Table(name: 'articles')]
class Article {
#[ORM\Id]
#[ORM\Column(type: 'integer')]
private int $id;
#[ORM\Column(length: 200, nullable: false)]
private string $titre = '';
}
// JPA (Spring Boot) : annotations Java
@Entity
@Table(name = "articles")
public class Article {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "titre", length = 200, nullable = false)
private String titre;
}
// EF Core (ASP.NET Core) : DataAnnotations C#
public class Article {
[Key]
public int Id { get; set; }
[Required, MaxLength(200)]
public string Titre { get; set; } = string.Empty;
}
DataAnnotations courantes
| Attribut | Description | SQL généré |
|---|---|---|
[Key] | Clé primaire | PRIMARY KEY |
[Required] | Valeur obligatoire | NOT NULL |
[MaxLength(200)] | Longueur maximale | VARCHAR(200) |
[StringLength(200)] | Longueur max + validation | VARCHAR(200) |
[Column("nom")] | Nom de colonne personnalisé | nom |
[Table("nom")] | Nom de table personnalisé | table nom |
[NotMapped] | Ignoré par EF Core | aucune colonne |
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] | Valeur auto-générée | AUTO_INCREMENT |
Par convention, si vous nommez votre propriété Id (ou NomClasseId), EF Core la reconnaît automatiquement comme clé primaire sans avoir besoin de [Key].
Propriétés de navigation
Les propriétés de navigation représentent les relations entre entités :
public class Article
{
public int Id { get; set; }
public string Titre { get; set; } = string.Empty;
// Clé étrangère vers Utilisateur
public int AuteurId { get; set; }
// Propriété de navigation (chargement de l'auteur)
public Utilisateur? Auteur { get; set; }
}
public class Utilisateur
{
public int Id { get; set; }
public string Nom { get; set; } = string.Empty;
// Un utilisateur peut avoir plusieurs articles (collection de navigation)
public List<Article> Articles { get; set; } = new();
}
Ces relations sont approfondies dans la séance 525.
Exemple pratique
Entité Article complète avec toutes les DataAnnotations pour MonBlog :
// Models/Article.cs
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace MonBlog.Models
{
[Table("articles")]
public class Article
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required(ErrorMessage = "Le titre est obligatoire")]
[MaxLength(200, ErrorMessage = "Le titre ne peut pas dépasser 200 caractères")]
[Display(Name = "Titre de l'article")]
public string Titre { get; set; } = string.Empty;
[Required(ErrorMessage = "Le contenu est obligatoire")]
[Display(Name = "Contenu")]
public string Contenu { get; set; } = string.Empty;
[Column("date_creation")]
[Display(Name = "Date de publication")]
public DateTime DateCreation { get; set; } = DateTime.UtcNow;
public bool EstPublie { get; set; } = false;
// Clé étrangère (relation avec Utilisateur — séance 525)
public int? AuteurId { get; set; }
public Utilisateur? Auteur { get; set; }
// Propriété calculée — pas de colonne en base
[NotMapped]
public string ResumeCourt => Contenu.Length > 150
? Contenu.Substring(0, 150) + "..."
: Contenu;
}
}
En C# avec les types nullable activés (.csproj avec <Nullable>enable</Nullable>), les string doivent être initialisées ou déclarées comme nullables (string?). L'initialisation à string.Empty est la convention EF Core.
Test de mémorisation/compréhension
TP pour réfléchir et résoudre des problèmes
Vous allez créer l'entité Article complète pour MonBlog.
Étape 1 — Créer la classe Article avec les propriétés de base
Utilisez le namespace MonBlog.Models pour toutes les entités. Ce namespace permet d'organiser et d'importer les classes facilement avec using MonBlog.Models; dans les contrôleurs et le DbContext.
Étape 2 — Ajouter les propriétés Titre et Contenu avec validation
Fournissez toujours un ErrorMessage dans [Required] et [MaxLength]. Ces messages s'affichent automatiquement dans les formulaires Razor si la validation échoue, offrant un retour clair à l'utilisateur.
Étape 3 — Ajouter la date de création avec un nom de colonne personnalisé
Stockez toujours les dates en UTC (Coordinated Universal Time) en base de données. Convertissez en heure locale uniquement lors de l'affichage. Cela évite les problèmes de fuseaux horaires, surtout si vos serveurs sont dans des zones géographiques différentes.