Blog IPgarde

Création d’une API avec Entity Framework Database First : Guide Pratique

Rédigé par Sylvain Grousset | Oct 2, 2023 8:41:00 AM

Dans cet article, je vais vous présenter comment créer, configurer et tester un projet WebAPI en utilisant ASP.NET Core 6.0 et EntityFramework Core.

Introduction

Une API est une interface de programmation (en anglais Application Programming Interface) qui permet à plusieurs composants logiciels de communiquer, de s’échanger des données.
Une API met à disposition une liste de ressources prédéfinies afin qu’elles soient utilisées par des applications tierces. 

Par exemple, l’administration française permet d’accéder aux informations concernant les entreprises et les établissements immatriculés au répertoire inter administratif Sirene de l’Insee. Un simple appel à l’Api retournera les informations de dénomination, SIREN, SIRET, NAF, date de création et de clôture, …

Dans cette première partie, je vais créer le projet avec Visual Studio que je configurerai afin de générer les éléments nécessaires à la création d’une API.

Dans la seconde partie, je passerai à la création d’une API avec l’utilisation d’un contrôleur et d’une route.

Prérequis 

  • Visual Studio 2019/2022 ;
  • .NET 6.0 SDK ;
  • SQL Server express ou autre.

 

Création du projet

Sur VisualStudio 2022 créer un nouveau projet API web ASP.NET Core

Définissez le nom et l’emplacement de votre projet puis suivant.

Afin de commencer un projet vide, décochez « Utiliser des contrôleurs » et veillez à bien sélectionner la version 6.0 du framework.

Schéma de base de données

Modèle Conceptuel de Données



Voici le schéma de base de données que je vais utiliser pour cet article. C’est une base de données avec simplement deux tables :

  • une table Utilisateurs
  • une table Métiers

Les utilisateurs peuvent être liés à un et un seul métier.  Nous avons donc une référence du métier dans la table Utilisateurs.

Script de création des tables :

 
 
 
 

Voici le jeu de données que j’utilise :

Configuration & génération

Comme énoncé en introduction, j’utilise la méthode Database-First dans le développement de cette application. Contrairement à l’approche Code-First, où l’on commence par définir les modèles de données, avec Database-First, on commence par créer initialement la base de données.

Ensuite, à partir de cette base de données existante, j’utilise la commande Scaffold-DbContext fournie par Entity Framework pour générer automatiquement les classes C# correspondantes. Cela me permet de démarrer avec une base de données préexistante et de créer les modèles de données C# associés de manière automatisée.

1.      Installation des packages

Afin d’utiliser Database-First avec EntityFramework, j’ai besoin des 2 packages ci-dessous :

Microsoft.EntityFrameworkCore.SqlServer <= Provider SqlServer
Microsoft.EntityFrameworkCore.Tools        <= Active une liste de commandes dont Scaffold-DbContext

Pour les installer, je vais utiliser la Console du Gestionnaire de Package :
Outils => Gestionnaire de package NuGet => Console du gestionnaire de package

 

2.      Ajout de la chaine de connexion

La commande Scaffold-DbContext prend en paramètre une chaine de connexion. Celle-ci doit être présente dans le fichier appsettings.json.

Voici la chaine de connexion :

 
 

Remplacez les informations en gras par :

  • SQLINSTANCE : Nom de votre instance SQL Server ;
  • DBNAME : Nom de votre base de données ;
  • USERNAME :  Nom d’utilisateur ayant les droits sur votre base de données ;
  • USERPASSWORD : Mot de passe de l’utilisateur

Ci-dessous ma chaine de connexion avec mes informations :

 
 

Muni de votre chaine de connexion complétée, il faut ajouter une entrée « ConnectionStrings » dans le fichier appsettings.json avec votre chaine de connexion :

 
 
 

3.      Utilisation de la commande Scaffold-DbContext

Voici la commande complète avec mes informations et mes paramètres :

 

Celle-ci prend en paramètres :

  • Connection qui cible le nom de votre chaine de connexion dans l’entrée ConnectionString de votre fichier appsettings.json (obligatoire et positionnel);
  • Provider qui est généralement le nom du package de votre base de données. Par exemple si à la place d’une base SQL Server j’avais voulu utiliser une base PostgreSQL, il aurait fallu que je télécharge le package Npgsql.EntityFrameworkCore.PostgreSQL et indiquer dans le provider le nom de ce package  (obligatoire et positionnel);
  • OutputDir le dossier de destination des dossiers générés (optionnel) ;
  • DataAnnotations qui permet d’utiliser les attributs sur les modèles aux lieux de l’API Fluent (optionnel) ;
  • NoOnConfiguring qui supprime la méthode NoOnConfiguring lors de la génération (optionnel).

La commande est à exécuter dans la console du gestionnaire de package.

  Attention, si votre projet ne compile pas correctement la commande s’exécutera en erreur.

Voici le dossier généré après exécution de la commande :

Dossier Models généré depuis la commande Scaffold-DbContext

Dans ce dossier, nous retrouvons les classes Metier.cs et Utilisateur.cs qui sont les 2 modèles correspondant aux tables de ma base de données :

Metier.cs

 
 
 

Utilisateur.cs

 
 
 

Vous pouvez noter la présence du champ Utilisateurs qui est une collection d’Utilisateurs dans le modèle Metier.cs.

 
 

Si on suit notre schéma de base de données, ce champ ne devrait pas exister car, un Utilisateur sait à quel métier il est associé mais on ne sait pas quels sont les utilisateurs associés à un métier donné.

Ce champ a été créé car, EntityFramework utilise une convention de génération des navigations par défaut bien spécifique en fonction du type de relation (un à plusieurs, plusieurs à plusieurs, un à un).

Ici, nous avons une relation de type un à plusieurs : un utilisateur n’a qu’un seul métier et un métier correspond à plusieurs utilisateurs.

Ainsi, lorsqu’EntityFramework est face à une relation de type un à plusieurs, celui-ci l’a traduit par une relation bidirectionnelle :
Un utilisateur sait à quel métier il est associé :

 
 

Et inversement, pour un métier donné, on sait les utilisateurs associés :

 
 

Cette Collection d’Utilisateurs posera des problèmes de récursivité.

Il faut ajouter l’attribut [JsonIgnore] pour indiquer à EntityFramework de ne plus sérialiser cette propriété, ce qui réglera ce problème de récursivité.

Et enfin, le dernier fichier généré est la classe la plus importante, WebAppContext.cs. Elle est responsable de toutes les interactions entre l’application et la base de données :

  • Création, transformation, exécution des requêtes ;
  • Gestion des transactions ;
  • Gestion de la concurrence ;
  • Gestion des relations ;
  • Suivi des modifications ;
  • Gérer les objets avec la base de données (Mapping Object-Relationnel (ORM)) ;

En résumé, dès que je souhaite faire une action quelconque sur la base de données (rechercher des données, insérer des données, mettre à jour des modifications, activer une transaction …) je vais devoir passer par cette classe.

4.       Ajout de dépendances

Afin de pouvoir faire des actions sur la base de données via la classe WebAppContext créée précédemment, il faut enregistrer cette classe dans le fournisseur de services d’application (conteneur d’injection). C’est ce qu’on appelle l’injection de dépendance.

Dans la classe Program.cs, j’ajoute l’injection de mon contexte via AddDbContext juste après la ligne var builder = WebApplication.CreateBuilder(args);

 
 

Puis, dans le contrôleur, je vais faire ce que l’on appelle de l’injection de constructeur pour accéder à ma classe de contexte et enfin pouvoir communiquer avec ma base de données.

Je vais ajouter une deuxième dépendance dans le conteneur d’injection qui concerne les contrôleurs (AddControlleurs()). Ligne a ajouter après  builder.Services.AddSwaggerGen();

 

Cette dépendance permet à l’application de savoir que je vais utiliser des contrôleurs. Sans cette dépendance il est impossible d’utiliser des contrôleurs dans mon application.

 

5.      Suppression du code généré par défaut

Avant de créer le premier contrôleur, je supprime toujours le code généré par défaut à la création du projet pour d’avantage de lisibilité.

En effet, lors de la création du projet, celui-ci a créé automatiquement un endpoint par défaut en guise d’exemple.

Il se situe dans le programme de démarrage Program.cs :

 
 
 

💡

Ce bout de code créé un endpoint /weatherforecast qui va retourner une liste de données météos générées aléatoirement.

 

Il est en effet possible de créer des endpoints à partir de la classe de démarrage. Cela est pratique pour un petit projet avec peu d’endpoints. Cependant pour des plus gros projets, il est indispensable de passer par des contrôleurs.

Supprimez le code ci-dessus du fichier Program.cs.

💡

Attention à ne pas supprimer par erreur la ligne app.Run(); qui se situe entre la déclaration du record WeartherForecast et l’Endpoint.

 

Conclusion

Nous avons appris, dans cette première partie à :

  • Créer un projet Visual Studio de type API
  • Configurer les accès à la base de données
  • Générer les classes correspondant aux tables de la base de données

Nous sommes désormais prêts à la création et la configuration d’un contrôleur et d’une route pour illustrer notre API.