Aller au contenu principal

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;
}
Comparaison avec Doctrine et JPA
// 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

AttributDescriptionSQL généré
[Key]Clé primairePRIMARY KEY
[Required]Valeur obligatoireNOT NULL
[MaxLength(200)]Longueur maximaleVARCHAR(200)
[StringLength(200)]Longueur max + validationVARCHAR(200)
[Column("nom")]Nom de colonne personnalisénom
[Table("nom")]Nom de table personnalisétable nom
[NotMapped]Ignoré par EF Coreaucune colonne
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]Valeur auto-généréeAUTO_INCREMENT
info

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;
}
}
Initialiser les strings

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


Quel attribut DataAnnotations marque une propriété comme clé primaire ?


Quel attribut rend une propriété obligatoire (NOT NULL) et ajoute une validation de formulaire ?


Quel attribut définit le nom de la colonne SQL pour une propriété C# ?


Quel attribut indique à EF Core d'ignorer une propriété (pas de colonne en base) ?


Quel est l'équivalent EF Core de l'attribut @Entity de JPA (Spring Boot) ?


Comment s'appelle la convention EF Core qui reconnaît automatiquement la clé primaire ?


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


Bonne pratique - Namespace pour les Models

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


Bonne pratique - Messages d'erreur explicites

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é


Bonne pratique - Utiliser DateTime.UtcNow

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.

📌 Une solution