Programmation .Net - Indépendance financière

Accéder aux données avec Entity Framework

Pour faire suite au dernier tutoriel sur Linq to SQL, le même exercice est possible avec Linq to Entities. En effet, l’objectif demeure de réduire la quantité de code SQL pour nous permettre de nous concentrer sur le code C# et de débugger à un seul endroit. De plus, on sépare mieux le code applicatif de la base de données. Cette ligne entre les deux peut devenir assez “floue” lors de l’utilisation des procédures stockées.

Deux choix s’offrent à nous, on peut soit y aller database first ou encore code first. En utilisant database first on crée d’abord la base de données puis nous utilisons le Entity Framework pour générer le model (reproduction de la base de données mais en code). À l’inverse, si on utilise code first, nous créons le model directement dans le code puis générons la base de données à partir de ce dernier. Personnellement je préfère utiliser database first et c’est ce que nous ferons dans ce tutoriel.

1. Mise en place de la base de données

Le scénario est que nous voulons garder en mémoire tous les objets ayant été vendus dans un ou plusieurs magasins. Nous aurons donc deux tables soit, Stores (magasins) et SoldItems (articles en vente) jointes par une liaison 1 vers plusieurs donc un magasin peut avoir plusieurs articles. Notre première étape est de créer physiquement la base de données.

Pour se faire, assurez-vous d’avoir SQL Server et SQL Management Studio d’installés sur votre ordinateur car nous en aurons besoin. En passant la portion configuration LAN du vidéo en lien n’est pas nécessaire pour ce tutoriel.

Voyez ci-dessous le code SQL pour la création de la base de données que nous allons utiliser. J’y ai ajouté quelques données que nous pourrons utiliser pour faire des opérations. Créez un nouveau script dans Management Studio en allant sur File -> New -> Script avec votre connexion courante. Copiez et collez le code suivant et appuyez sur exécuter. Cliquez droit sur votre serveur et puis sur rafraîchir.

CREATE DATABASE [Corporation]
GO
USE [Corporation]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[SoldItems](
	[SoldItemID] [int] IDENTITY(1,1) NOT NULL,
	[StoreID] [int] NOT NULL,
	[Number] [int] NOT NULL,
	[Description] [varchar](150) NOT NULL,
	[Price] [money] NOT NULL,
	[Quantity] [int] NOT NULL,
 CONSTRAINT [PK_SoldItems] PRIMARY KEY CLUSTERED 
(
	[SoldItemID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO


SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Stores](
	[StoreID] [int] IDENTITY(1,1) NOT NULL,
	[Name] [varchar](50) NOT NULL,
	[Street] [varchar](50) NOT NULL,
	[StreetNumber] [varchar](10) NOT NULL,
	[City] [varchar](50) NOT NULL,
	[Country] [varchar](50) NOT NULL,
	[IsActive] [bit] NOT NULL,
 CONSTRAINT [PK_Stores] PRIMARY KEY CLUSTERED 
(
	[StoreID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET IDENTITY_INSERT [dbo].[SoldItems] ON 

INSERT [dbo].[SoldItems] ([SoldItemID], [StoreID], [Number], [Description], [Price], [Quantity]) VALUES (1, 1, 985649082, N'Shoes', 60.0000, 1)
INSERT [dbo].[SoldItems] ([SoldItemID], [StoreID], [Number], [Description], [Price], [Quantity]) VALUES (2, 2, 439849329, N'T-Shirt with logo', 70.0000, 2)
INSERT [dbo].[SoldItems] ([SoldItemID], [StoreID], [Number], [Description], [Price], [Quantity]) VALUES (3, 1, 328494300, N'Black Jeans', 100.0000, 1)
INSERT [dbo].[SoldItems] ([SoldItemID], [StoreID], [Number], [Description], [Price], [Quantity]) VALUES (4, 1, 432874373, N'Blue Jeans', 60.0000, 3)
SET IDENTITY_INSERT [dbo].[SoldItems] OFF
SET IDENTITY_INSERT [dbo].[Stores] ON 

INSERT [dbo].[Stores] ([StoreID], [Name], [Street], [StreetNumber], [City], [Country], [IsActive]) VALUES (1, N'StoreOne', N'Test', N'12', N'Pie', N'United States', 1)
INSERT [dbo].[Stores] ([StoreID], [Name], [Street], [StreetNumber], [City], [Country], [IsActive]) VALUES (2, N'Monument', N'Gray', N'454', N'Super', N'Canada', 1)
SET IDENTITY_INSERT [dbo].[Stores] OFF
ALTER TABLE [dbo].[SoldItems]  WITH CHECK ADD  CONSTRAINT [FK_SoldItems_Stores] FOREIGN KEY([StoreID])
REFERENCES [dbo].[Stores] ([StoreID])
ON DELETE CASCADE
GO
ALTER TABLE [dbo].[SoldItems] CHECK CONSTRAINT [FK_SoldItems_Stores]
GO
USE [master]
GO
ALTER DATABASE [Corporation] SET  READ_WRITE 
GO

Note: remarquez le On delete cascade faisant en sorte que la suppression d’un magasin (Store) supprime aussi les articles (SoldItem) liés à ce dernier.

Voici le résultat final après la création de la base de données dans SQL Management Studio.

Linq To Entities

2. Création d’un nouveau projet

Créez un nouveau projet dans Visual Studio, une application Console ou encore Windows Forms fera l’affaire!

Create New Project

3. Ajout d’un nouvel Entity Context ADO.Net

Le Entity Context de ADO.Net nous fournira une interface conviviale pour y ajouter des tables ainsi que des procédures stockées au besoin. Elle servira de liaison pour faire des commandes Linq vers la base de données. Comme du SQL sans du SQL, n’est-ce pas génial!

Je vous suggère de créer deux nouveaux fichiers à l’intérieur de votre projet Visual Studio C# pour organiser la couche d’accès aux données. Plus précisément DataAccess -> DataObjects comme montré ci-dessous. Cliquez droit sur DataObject puis Add, New Item…

Data Access folders.

Il est maintenant temps d’ajouter le Entity Data Context. Sélectionnez ADO.NET Entity Data Model et donnez-lui un nom. Le mien s’appellera Corporation puisque Visual Studio nommera la classe principale CorporationEntities. Donc le nom que vous lui donnerez suivit du mot Entities.

Create Entity Data Context.

Une fois que vous aurez nommé votre Data Context, cliquez sur Add et vous serez redirigé vers une autre fenêtre comme celle qui suit. Sélectionnez EF Designer from database.

Database first Entity Context.

Ensuite, Visual Studio vous demandera la connexion que vous désirez utiliser. Cliquez sur New Connection puis sélectionnez SQL Server Connection.

Select SQL Serveur Connection.

Cliquez sur suivant et nous allons entrer les paramètres d’autorisation vers notre base de données. La première section vous demande le nom de votre serveur et de l’instance sous la forme NOMDUSERVEUR\NOMDELINSTANCESQLSERVEUR. Dans le cas de mon PC, son nom est Vier mais le vôtre sera assurément nommé autrement. Pour le savoir, faites Windows Logo + Q sur votre clavier et écrivez This PC (Ce PC si votre ordinateur est en français). Puis cliquez droit sur l’icône et cliquez sur Properties.

Pour ce qui est de l’instance SQL, elle sera probablement SQLEXPRESS si vous avez téléchargé la même version que moi et que vous n’avez pas changé le nom par défaut de l’instance. Vous pouvez rester avec Windows Authentication pour le moment puis sélectionnez le nom de votre base de données dans la liste déroulante comme montrée ci-dessous.

Vous pouvez tester vos paramètres en cliquant sur le bouton Test Connection.

Create a new connection to the database.

Sélectionnez Entity Framework 6.x qui est en ce moment le plus récent.

Entity Framework selection.

Choisissez les composants que vous voulez ajouter au Entity data model. Dans notre cas nous ajouterons seulement les tables puisque nous n’avons pas de views ni de procédures stockées.

Components selection.

Et voilà! Une fois que vous aurez cliqué sur finish Visual Studio générera quelque chose comme ce que vous pouvez voir dans l’image suivante. Étrange, le sysdiagram entity a été ajouté et nous n’en avons pas besoin donc on peu la supprimer en cliquant dessus puis sur la touche suppr. ou delete de votre clavier.

Created data context.

4. Modification du Data Model

Le modèle est présentement statique et donc doit être mis à jour si vous faites de modifications à votre base de données. Il ne se synchronise pas automatiquement et pour faire cette action vous devez cliquer droit sur le fond de l’écran du Entity model diagram puis sur Update Model from database.

Update Entity Model.

Une fenêtre montrant trois onglets apparaîtra. La première sert à ajouter des nouveaux éléments, la deuxième à seulement rafraîchir les éléments existants et la troisième à les supprimer. Pour le moment nous n’avons rien à ajouter donc vous pouvez simplement aller sur l’onglet Refresh puis sélectionner Tables si vous voulez mettre à jour toutes les tables d’un seul coup.

Note: Selon mon expérience toutefois, le schéma est toujours mis à jour au complet quand même peut-importe ce que vous ferez comme modifications dans les onglets ajouter et supprimer.

Add Update Delete Entities.

5. Création des classes d’accès aux données

J’ai créé deux classes d’accès aux données que j’appelle Data Links. Nous les utiliserons pour accomplir des opérations de base sur des tables spécifiques. Remarquez que chaque table a son Data Link associé. Vous pouvez utiliser un autre façon de séparer vos classes d’accès aux données de votre logique d’affaires toutefois j’ai remarqué que cette méthode fonctionne très bien pour des projets de petite à moyenne envergure.

Voyez ci-dessous les deux classes qui ont été créées. Vous pouvez faire de même en cliquant droit sur le fichier DataAccess puis sur Add -> New Item… -> Class.

Create Data Links

Remarquez que le namespace LinqToEntities.DataAccess.DataObjects correspond à la structure de fichier dans laquelle il se trouve. Les méthodes suivantes effectuent des opérations de bases soit la création, la mise à jour, la suppression et la récupération d’information. Elles montrent aussi le pouvoir de Linq pour accéder aux données.

StoresDataLink.cs

using System;
using System.Collections.Generic;
using System.Linq;

using LinqToEntities.DataAccess.DataObjects;

namespace LinqToEntities.DataAccess
{
    public class StoresDataLink
    {
        private CorporationEntities _CorporationEntities;

        /// <summary>
        /// Constructeur sans paramètre pour implémentation seule de la classe.
        /// </summary>
        public StoresDataLink()
        {
            _CorporationEntities = new CorporationEntities();
        }

        /// <summary>
        /// Constructeur avec paramètre pour utilisation avec des transactions.
        /// </summary>
        /// 
        /// <param name="corporationEntities">Un object CorporationEntities déjà initialisé.</param>
        public StoresDataLink(CorporationEntities corporationEntities)
        {
            _CorporationEntities = corporationEntities;
        }

        /// <summary>
        /// Récupère un object store (magasin) depuis la base de données.
        /// </summary>
        /// 
        /// <param name="storeID">L'identifiant du magasin à récupérer.</param>
        /// 
        /// <returns>Un objet de type Store.</returns>
        public Store Retrieve(int storeID)
        {
            if (!Exists(storeID))
                throw new ArgumentException("L'identifiant du Store fourni n'existe pas.");

            Store foundStore = _CorporationEntities.Stores.Single(store => store.StoreID == storeID);

            return foundStore;
        }

        /// <summary>
        /// Récupère tous les magasins dans la base de données.
        /// </summary>
        /// 
        /// <returns>Un IEnumerable contenant les magasins.</returns>
        public IEnumerable<Store> RetrieveAll()
        {
            IEnumerable<Store> stores = _CorporationEntities.Stores;

            return stores;
        }

        /// <summary>
        /// Ajoute un objet Store à la base de données.
        /// </summary>
        /// 
        /// <param name="store">L'objet Store à ajouter.</param>
        /// <returns>L'objet ajouté avec son identifiant généré.</returns>
        public Store Add(Store store)
        {
            Store addedStore = _CorporationEntities.Stores.Add(store);
            _CorporationEntities.SaveChanges();

            return addedStore;
        }

        /// <summary>
        /// Met à jour un objet Store dans la base de données. Sans son identifiant car ce dernier est utilisé pour récupérer l'objet.
        /// </summary>
        /// 
        /// <param name="store">L'objet Store à mettre à jour dans base de données.</param>
        public void Update(Store store)
        {
            if (!Exists(store.StoreID))
                throw new ArgumentException("L'identifiant du Store fourni n'existe pas.");

            Store storeToUpdate = _CorporationEntities.Stores.Single(selectedstore => selectedstore.StoreID == store.StoreID);

            storeToUpdate = store;
            _CorporationEntities.SaveChanges();
        }

        /// <summary>
        /// Supprime plusieurs éléments de type Store dans la base de données. Ne pas utiliser pour supprimer une grande quantité d'éléments.
        /// </summary>
        /// 
        /// <param name="storeID">L'identifiant du Store à supprimer.</param>
        public void Delete(int storeID)
        {
            if (!Exists(storeID))
                throw new ArgumentException("L'identifiant du Store fourni n'existe pas.");

            Store storeToDelete = _CorporationEntities.Stores.Single(selectedstore => selectedstore.StoreID == storeID);

            _CorporationEntities.Stores.Remove(storeToDelete);
            _CorporationEntities.SaveChanges();
        }

        /// <summary>
        /// Supprime plusieurs Store à la fois dans la base de données.
        /// </summary>
        /// 
        /// <param name="stores">The Stores to delete.</param>
        public void DeleteAll(IEnumerable<Store> stores)
        {
            _CorporationEntities.Stores.RemoveRange(stores);
            _CorporationEntities.SaveChanges();
        }

        /// <summary>
        /// Vérifie si un Store existe dans la base de données.
        /// </summary>
        /// 
        /// <param name="soldItemID">L'identifiant du Store à vérifier.</param>
        /// 
        /// <returns>True si l'élément existe, False s'il n'existe pas.</returns>
        public bool Exists(int storeID)
        {
            if (_CorporationEntities.Stores.Any(store => store.StoreID == storeID))
                return true;
            return false;
        }

        /// <summary>
        /// Compte le nombre de Store dans la base de données.
        /// </summary>
        /// 
        /// <returns>Le nombre de Store.</returns>
        public int CountAll()
        {
            return _CorporationEntities.Stores.Count();
        }
    }
}

SoldItemsDataLink.cs

Si vous voulez accéder à des éléments d’inventaires spécifiques ou en ajouter, vous pouvez utiliser la classe SoldItemsDataLink. Pour les exemples plus bas je vais uniquement montrer la classe StoreDataLink en action, mais vous pouvez tester la suivante par vous même aussi.

using System;
using System.Collections.Generic;
using System.Linq;

using LinqToEntities.DataAccess.DataObjects;

namespace LinqToEntities.DataAccess
{
    public class SoldItemsDataLink
    {
        private CorporationEntities _CorporationEntities;

        /// <summary>
        /// Constructeur sans paramètre pour implémentation seule de la classe.
        /// </summary>
        public SoldItemsDataLink()
        {
            _CorporationEntities = new CorporationEntities();
        }

        /// <summary>
        /// Constructeur avec paramètre pour utilisation avec des transactions.
        /// </summary>
        /// 
        /// <param name="corporationEntities">Un object CorporationEntities déjà initialisé.</param>
        public SoldItemsDataLink(CorporationEntities corporationEntities)
        {
            _CorporationEntities = corporationEntities;
        }
        
        /// <summary>
        /// Récupère un SoldItem (élément en vente) de la base de données.
        /// </summary>
        /// 
        /// <param name="soldItemID">L'identifiant d'un élément en vente.</param>
        /// 
        /// <returns>Un objet de type SoldItem.</returns>
        public SoldItem Retrieve(int soldItemID)
        {
            if (!Exists(soldItemID))
                throw new ArgumentException("The SoldItemID provided does not exist.");

            SoldItem foundItem = _CorporationEntities.SoldItems.Single(solditem => solditem.SoldItemID == soldItemID);

            return foundItem;
        }

        /// <summary>
        /// Récupère tout les SoldItems de la base de données.
        /// </summary>
        /// 
        /// <returns>Un IEnumerable contenant tout les SoldItems.</returns>
        public IEnumerable<SoldItem> RetrieveAll()
        {
            IEnumerable<SoldItem> soldItems = _CorporationEntities.SoldItems;

            return soldItems;
        }

        /// <summary>
        /// Ajoute un SoldItem à la base de données.
        /// </summary>
        /// 
        /// <param name="soldItem">Le SoldItem à ajouter.</param>
        public void Add(SoldItem soldItem)
        {
            _CorporationEntities.SoldItems.Add(soldItem);
            _CorporationEntities.SaveChanges();
        }

        /// <summary>
        /// Met à jour un SoldItem dans la base de données à l'aide de son identifiant.
        /// </summary>
        /// 
        /// <param name="soldItem">Le SoldItem à modifier contenant l'identifiant.</param>
        public void Update(SoldItem soldItem)
        {
            if (!Exists(soldItem.SoldItemID))
                throw new ArgumentException("The SoldItemID provided does not exist.");

            SoldItem soldItemToUpdate = _CorporationEntities.SoldItems.Single(solditem => solditem.SoldItemID == soldItem.SoldItemID);

            soldItemToUpdate = soldItem;
            _CorporationEntities.SaveChanges();
        }

        /// <summary>
        /// Supprime un SoldItem de la base de données.
        /// </summary>
        /// 
        /// <param name="soldItemID">L'identifiant du SoldItem à supprimer.</param>
        public void Delete(int soldItemID)
        {
            if (!Exists(soldItemID))
                throw new ArgumentException("The SoldItemID provided does not exist.");

            SoldItem soldItemToDelete = _CorporationEntities.SoldItems.Single(solditem => solditem.SoldItemID == soldItemID);

            _CorporationEntities.SoldItems.Remove(soldItemToDelete);
            _CorporationEntities.SaveChanges();
        }

        /// <summary>
        /// Vérifie si un SoldItem existe dans la base de données.
        /// </summary>
        /// 
        /// <param name="soldItemID">L'identifiant du SoldItem à vérifier.</param>
        /// 
        /// <returns>True si l'élément existe, False s'il n'existe pas.</returns>
        public bool Exists(int soldItemID)
        {
            if (_CorporationEntities.SoldItems.Any(solditem => solditem.SoldItemID == soldItemID))
                return true;
            return false;
        }
    }
}

6. Accès aux données

Faisons quelques opérations de bases pour montrer à quel point il est facile d’utiliser Entity Framework pour accéder aux données. La raison pour laquelle j’utilise les DataLinks dans mon exemple est que je souhaite, comme je disais plus tôt, mieux séparer les différentes parties de l’application. Les DataLinks se chargent exclusivement d’accéder aux informations en utilisant le Entity Framework. Le reste de la logique est accomplie par d’autres modules. C’est comme une barrière entre l’application et la base de données si vous voulez.

Voici une représentation graphique de ce que j’entends par séparations des parties de l’application.

Data Links Pattern

J’admets qu’utiliser les DataLinks ajoute une certaine complexité. Toutefois, une fois que le projet prend plus d’ampleur, on peut réellement voir les bénéfices de séparer l’application en 3 couches. On augmente ainsi le couplage en réutilisant les mêmes méthodes pour accéder aux données de différents endroits dans l’application. De ce fait, n’importe quelle portion de l’application doit passer par les DataLinks pour effectuer un accès.

Vous êtes quand même libre d’utiliser ma méthode ou encore d’accéder aux données directement en avec le Entity Framework de n’importe où dans l’application.

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using LinqToEntities.DataAccess;
using LinqToEntities.DataAccess.DataObjects;

namespace LinqToEntities
{
    class Program
    {
        static void Main(string[] args)
        {
            //Si vous voulez voir uniquement l'accès aux données, passez à la section : Accès aux données direct avec Entity Framework.

            //-----------Completing data operations using DataLinks------------//
            CorporationEntities corporationEntities = new CorporationEntities();

            StoresDataLink storesDataLink = new StoresDataLink(corporationEntities);
            SoldItemsDataLink soldItemsDataLink = new SoldItemsDataLink(corporationEntities);

            //Cleanup database
            Console.WriteLine("Stores cleanup...");
            IEnumerable<Store> storesToCleanup = storesDataLink.RetrieveAll();
            storesDataLink.DeleteAll(storesToCleanup);

            Console.WriteLine("Number of stores in the database after cleanup... {0}", storesDataLink.CountAll());

            //Une façon d'initialiser un object Store.
            Store storeOneToAdd = new Store();
            storeOneToAdd.Name = "Test Store";
            storeOneToAdd.Street = "front st.";
            storeOneToAdd.StreetNumber = "78-1";
            storeOneToAdd.City = "Toronto";
            storeOneToAdd.Country = "Canada";
            storeOneToAdd.IsActive = true;

            //L'identifiant sera créé automatiquement puisqu'il est auto-incrémenté dans la base de données.
            //Nous pourrions aussi récupérer l'élément ajouté pour regarder l'identifiant généré.
            storesDataLink.Add(storeOneToAdd);

            //Dans ce second objet, je met directement les SoldItems dans l'objet Store, ces derniers seront ajoutés automatiquement aussi! Facile!
            //Une autre façon d'initialiser un objet Store.
            Store storeTwoToAdd = new Store()
            {
                Name = "Store With Items",
                Street = "Back st.",
                StreetNumber = "77-2",
                City = "Toronto",
                Country = "Canada",
                IsActive = true
            };

            //Ajout d'un SoldItem directement. Encore une fois pas besoin de spécifier son identifiant car il sera auto-généré par la base de données.
            storeTwoToAdd.SoldItems.Add(new SoldItem()
            {
                Number = 97843278,
                Description = "Blackberry Priv",
                Price = 499.99m,
                Quantity = 60
            });

            //Je vais chercher le Store ajouté en même temps, pourquoi pas!
            Store addedStore = storesDataLink.Add(storeTwoToAdd);
            Console.WriteLine("--Added Store--");
            OutputStoreInConsole(addedStore);

            //Mettons à jour le Store que nous venons d'ajouter en changeant son nom.
            Store storeToUpdate = storesDataLink.Retrieve(addedStore.StoreID);
            storeToUpdate.Name = "Super Store";

            storesDataLink.Update(storeToUpdate);

            //Nous allons aller chercher le Store une fois de plus pour prouvé qu'il a bel et bien été mis à jour. Pas besoin de faire cette opération en temps normal.
            Store updatedStore = storesDataLink.Retrieve(addedStore.StoreID);
            OutputStoreInConsole(updatedStore);

            bool storeExistsPriorToDeletion = storesDataLink.Exists(updatedStore.StoreID);
            Console.WriteLine("Store exists prior to deletion : {0}", storeExistsPriorToDeletion);

            //Pour vous montrer comment supprimer, voici la méthode Delete.
            storesDataLink.Delete(updatedStore.StoreID);
            bool storeExists = storesDataLink.Exists(updatedStore.StoreID);
            Console.WriteLine("Deletion result store still exists in the database : {0}", storeExists);



            //-------Opérations executées une fois de plus en utilisant le Entity Framework directement.--------//

            //Juste pour réinitialiser la base de données avant de recommencer.
            Console.WriteLine("Stores cleanup...");
            IEnumerable<Store> storesToCleanupEF = corporationEntities.Stores;

            corporationEntities.Stores.RemoveRange(storesToCleanupEF);
            corporationEntities.SaveChanges();

            Console.WriteLine("Number of stores in the database after cleanup... {0}", corporationEntities.Stores.Count());

            //Ajout
            //Nous allons ajouter deux Store de deux façons différentes.
            Store storeOneToAddEF = new Store();
            storeOneToAddEF.Name = "Test Store EF";
            storeOneToAddEF.Street = "front st.";
            storeOneToAddEF.StreetNumber = "78-1";
            storeOneToAddEF.City = "Toronto";
            storeOneToAddEF.Country = "Canada";
            storeOneToAddEF.IsActive = true;

            corporationEntities.Stores.Add(storeOneToAddEF);
            //SaveChanges() doit être appelé pour que les opérations soient refétées sur la base de données. Vous pouvez en faire plus d'une à la fois.
            corporationEntities.SaveChanges();

            Store storeTwoToAddEF = new Store()
            {
                Name = "Store With Items EF",
                Street = "Back st.",
                StreetNumber = "77-2",
                City = "Toronto",
                Country = "Canada",
                IsActive = true
            };

            storeTwoToAddEF.SoldItems.Add(new SoldItem()
            {
                Number = 97843278,
                Description = "Blackberry Priv EF",
                Price = 499.99m,
                Quantity = 60
            });

            Store addedStoreEF = corporationEntities.Stores.Add(storeTwoToAddEF);
            corporationEntities.SaveChanges();

            Console.WriteLine("--Added Store EF--");
            OutputStoreInConsole(addedStoreEF);

            //Mise à jour
            //Nous allons mettre à jour le Store que nous avons ajouté précédamment.
            Store storeToUpdateEF = corporationEntities.Stores.Single(store => store.StoreID == addedStoreEF.StoreID);
            storeToUpdateEF.Name = "Updated Store Name EF";

            //Il n'est pas nécessaire d'appeler une méthode en particulier pour mettre à jour car les changements seront reflétés directement par le Entity Framework.
            //Une fois modifié, l'élément sera considéré comme modifié par le Entity Framework et sera mis à jour automatiquement après l'appel de SaveChanges().
            corporationEntities.SaveChanges();
            OutputStoreInConsole(storeToUpdateEF);

            //Selection et suppression
            //Nous allons supprimer le Store que nous venons de mettre à jour.
            //Je fais quand même une vérification que le Store existe même si ça ne garantie pas qu'il sera bien là au moment de la suppression. Le code lancera une exception si c'est le cas.
            if (corporationEntities.Stores.Any(store => store.StoreID == storeToUpdateEF.StoreID))
            {
                //Récupère le Store qui sera supprimé en utilisant Single().
                Store storeToDelete = corporationEntities.Stores.Single(store => store.StoreID == storeToUpdateEF.StoreID);

                corporationEntities.Stores.Remove(storeToDelete);
                corporationEntities.SaveChanges();
            }

            //Juste pour s'assurer que le Store que nous venons de supprimer n'existe réellement plus.
            bool storeExistsEF = corporationEntities.Stores.Any(store => store.StoreID == storeToUpdateEF.StoreID);
            Console.WriteLine("Deletion result store still exists in the database : {0}", storeExistsEF);

            Console.ReadKey();
        }

        private static void OutputStoreInConsole(Store storeToOutput)
        {
            Console.WriteLine("Store Object : StoreID {0}, Name {1}, Street {2}, StreetNumber {3}, City {4}, Country {5}, IsActive {6}",
                               storeToOutput.StoreID,
                               storeToOutput.Name,
                               storeToOutput.Street,
                               storeToOutput.StreetNumber,
                               storeToOutput.City,
                               storeToOutput.Country,
                               storeToOutput.IsActive);
        }
    }
}

J’ai ajouté quelques Console.WriteLine() mais je vous suggère très fortement de mettre des points d’arrêt pour simplifier votre tâche et voir comment le code fonctionne pas à pas. Plusieurs commentaires on aussi été dispersés dans le code pour tenter de clarifier davantage.

Conclusion: Entity Framework vs Linq to SQL

Sur une notre finale pour conclure les deux tutoriels. Entity Framework et Linq to SQL sont des technologies comparables avec quelques différences que vous pouvez explorer sur Stack Overflow (anglais seulement). En tout les cas, les deux nous rendent la vie beaucoup plus simple et permettent d’utiliser Linq pour accéder aux données. Que ce soit avec SQL Server ou encore un autre connecteur comme MySQL (Voir .Net Core). Utilisez la technologie que vous préférez et bénéficiez d’une rapidité de codage bien supérieure à ces bonnes vieilles procédures stockées. Quoiqu’elles peuvent être encore utiles parfois pour des cas précis qui demande de la performance.

En bref, j’espère bien que ces technologies vous serviront aussi bien qu’elles le font dans mon travail de tout les jours. Bon code!

Lecture suggérée

J’aimerais vous suggérer la lecture de ce livre (anglais seulement) si vous voulez plus d’information sur le sujet du Entity Framework ou encore sur C# et .Net en général. Je m’y réfère souvent lorsque j’ai besoin d’information ou d’exemples rapidement.

Vous avez trouvé un bogue dans mon code? C’est possible, veuillez m’envoyer un message en utilisant mon formulaire de contact pour que je puisse remédier à la situation aussi rapidement que possible!

Youtube

Partie 1 – Mise en place

Partie 2 – DataLinks

Partie 3 – Opérations sur la base de données

Next article Comment créer un nouveau projet dans Visual Studio
Previous article Utiliser le REER et le CELI comme levier d'indépendance financière

Related posts

0 Comments

No Comments Yet!

You can be first to comment this post!

Leave a Comment

Your data will be safe! Your e-mail address will not be published. Also other data will not be shared with third person. Required fields marked as *