Développement dapplication avec base de données Semaine 10 : WCF avec Entité Framework Automne...

Preview:

Citation preview

Développement d’application avec base de données

Semaine 10 : WCF avec Entité FrameworkAutomne 2013

Dans ce cours, nous allons voir l’utilisation de l’entité Framework avec les services WCF et quels complications(et solutions) peuvent survenir.

Introduction

Architecture Création de la partie serveur Création de la partie client Exercices

Plan de présentation

Architecture

L’utilisation de l’entité framework nous aidera à gérer la base de données du côté service.

Par contre, du côté client, EntityCollections n’existera pas de la même manière. Par exemple, les objets en relations avec les autres seront stocké dans des List plutôt que dans un EntityCollections.

Un autre différence est que les propriétés de navigations ne seront pas automatiquement dans les deux directions.

De plus, il faut garder à l’esprit que les modifications stockés dans ObjectStateEntry seront perdues une fois transféré au service.

Mise en garde

Une mauvaise choses pour les clients qui n’utilisent pas le .Net.

De plus, la sérialisation(protocole du service) fait que les objets EntityObject sont très gros.

Par contre, si l’on est certain d’utiliser un client .Net, cela nous simplifie énormément le travail.

Retourner des EntityObjects de la part du service: Bon ou Mauvais?

1. Créer un projet(exemple Console) qui utilise qui utilise l’entité Data Modèle

2. Ajouter un projet « Application du service WCF »

Construire un service avec l’entité Framework

Renommer(partout dans le projet) IService1 pour quelque chose de plus significatif.

Ajouter une référence à System.Data.Entity Copier la section ConnectionStrings de votre

projet Modèle (app.config) vers votre projet Service(web.config)

Construire un service avec l’entité Framework

1. Ouvrir le fichier de l’interface (exemple : ICustomerService).

2. Supprimer les opérations par défaut GetData et GetDataUsingDataContract.

3. Ajouter le bon usign de votre EDM.4. Ajouter les méthodes “OperationContract”

dans votre interface

Construire un service avec l’entité Framework

Construire un service avec l’entité Framework

[ServiceContract] public interface IContactAddresses { [OperationContract] List<Contact> GetAllContacts(); [OperationContract] Contact GetContact(int contactId); [OperationContract] string UpdateContact(Contact contact); [OperationContract] string DeleteContact(int contactId); [OperationContract] string InsertContact(Contact contact); }

Construire un service avec l’entité Framework

Il est possible de définir de nouveaux types qui pourront être utilisés du côté client(définis dans le WSDL) avec le mot-clé [DataContract()](et par conséquent [DataMember()]).

C’est maintenant le temps d’ajouter de la logique à notre service

1. Supprimer les méthodes par défauts.2. Ajouter les bons using.3. Implémenter l’interface du service4. Ajouter le code pour retrouver la liste des

contacts

Implémenter l’interface du service

Construire un service avec l’entité Framework

public List<Contact> GetAllContacts() { using (var context = new PROGRAMMINGEFDB1Entities()) { context.Configuration.LazyLoadingEnabled = false; List<ClientService.Contact> resultat = context.Contact.OrderBy(c => c.LastName + c.FirstName).ToList(); return resultat; } }

Recommandation

Lorsqu’on utilise un service Web, il faut que la durée de vie du contexte(et sa connexion) soit la plus courte possible.

Pourquoi? Pour éviter d’avoir plusieurs contextes entres

les différents clients qui soit désynchronisés.

Attention avec le Lazy Loading. Il est préférable de le désactiver et de gérer nous-même les éléments transférés.

La sérialisation lors d’un transfert essaiera de récupérer les entités reliés.

Pour tester votre nouvelle fonction, vous pouvez suivre les étapes(voir plus bas)

Construire un service avec l’entité Framework

La méthode GetContact

public Contact GetContact(int contactId) { using (var context = new PROGRAMMINGEFDB1Entities()) { context.Configuration.LazyLoadingEnabled = false; Contact contact = context.Contact.Include("Address").Where(c => c.ContactID == contactId).Single(); return contact; } }

Construire un service avec l’entité Framework

InsertContact Il y a plusieurs choses à savoir si l’on veut

ajouter un contact: Les valeurs par défaut définies dans le modèle ne

sont pas sérialisé. Si on veut ajouter les éléments en liens avec une

entité, il faut utiliser le mot clé [DataContract(IsReference = true)] pour éviter une référence cyclique lors de la sérialisation. .. Par contre les performances seront moindres.

Construire un service avec l’entité Framework

[DataContract(IsReference = true)] public partial class Contact { public Contact() { this.Address = new List<Address>(); } [DataMember] public int ContactID { get; set; } [DataMember] public string FirstName { get; set; } [DataMember] public string LastName { get; set; } [DataMember] public string Title { get; set; } [DataMember] public System.DateTime AddDate { get; set; } [DataMember] public System.DateTime ModifiedDate { get; set; } [DataMember] public virtual ICollection<Address> Address { get; set; } }

Construire un service avec l’entité Framework

[DataContract(IsReference = true)] public partial class Address { [DataMember] public int addressID { get; set; } [DataMember] public string Street1 { get; set; } [DataMember] public string Street2 { get; set; } [DataMember] public string City { get; set; } [DataMember] public string StateProvince { get; set; } [DataMember] public string CountryRegion { get; set; } [DataMember] public string PostalCode { get; set; } [DataMember] public string AddressType { get; set; } [DataMember] public int ContactID { get; set; } [DataMember] public System.DateTime ModifiedDate { get; set; } [DataMember] public virtual Contact Contact { get; set; } }

Construire un service avec l’entité Framework

public string InsertContact(Contact contact) { try { using (var context = new ClientService.PROGRAMMINGEFDB1Entities()) { context.Contact.Add(contact); context.SaveChanges(); } return contact.ContactID.ToString(); } catch (Exception ex) { string errorMessage = ex.Message; return errorMessage; } }

Construire un service avec l’entité Framework

Supprimer un contact et ses adresses public string DeleteContact(int contactId) { try { using (PROGRAMMINGEFDB1Entities context = new PROGRAMMINGEFDB1Entities()) { Contact contact = context.Contact.Include("Address").Where(c => c.ContactID == contactId).Single(); var addresssToDelete = contact.Address.ToList(); foreach (Address a in addresssToDelete) { context.Address.Remove(a); } context.Contact.Remove(contact); context.SaveChanges(); return "Success"; } } catch (Exception ex) { string errorMessage = ex.Message; return errorMessage; } }

Construire un service avec l’entité Framework

Lors de la modification d’un contact un problème s’impose: Comment savoir ce qui a été modifié, ajouté ou supprimer.

Comme nous n’avons pas accès au ChangeTracker du côté client, il faudra utiliser une astuce pour faire la modification.

Construire un service avec l’entité Framework

Au niveau du service, nous allons définir un nouveau type pour la modification d’un contact(ContactUpdate).

Ce nouveau type contiendra le Contact et ses adresses modifié et ajouté. De plus, il contiendra la liste des numéro d’adresse à supprimer.

Et comme On sait qu’une nouvelle adresse à un id < 0, il ne restera qu’à traiter indépendamment les trois cas possibles (Ajouter, Modifier et Supprimer)

Construire un service avec l’entité Framework

[DataContract()] public class ContactUpdate { [DataMember()] public ClientService.Contact Contact { get; set; } [DataMember()] public List<int> AdressesToDelete { get; set; } }

Construire un service avec l’entité Framework

public string UpdateContact(ContactUpdate contact) { try { var modifiedContact = contact.Contact; using (var context = new PROGRAMMINGEFDB1Entities()) { context.Contact.Attach(modifiedContact); context.Entry(modifiedContact).State = EntityState.Modified; context.Configuration.LazyLoadingEnabled = false; foreach (Address address in modifiedContact.Address) { if (address.addressID > 0) { context.Entry(address).State = EntityState.Modified; } else { context.Entry(address).State = EntityState.Added; } } context.Configuration.LazyLoadingEnabled = true; //Code for Deleted Reservations will go here; List<int> addressToDelete = contact.AdressesToDelete; DeleteAddress(context, addressToDelete); context.SaveChanges(); } return "Success"; } catch (Exception ex) { return "Error: " + ex.Message; } }

Construire un service avec l’entité Framework

private void DeleteAddress(PROGRAMMINGEFDB1Entities context, List<int> addressesToDelete) { if (null != addressesToDelete) { var query = from address in context.Address join addressId in addressesToDelete on address.addressID equals addressId select address; foreach (var address in query) { context.Address.Remove(address); } } }

1. Créer un nouveau projet Console ou Windows Form.

2. Ajouter une référence à un Service. Clique droit sur le nouveau projet et sélectionner “Ajouter une référence de service”

Construire un client qui utilise un service avec l’entité Framework

Cliquer sur le bouton Avancé… et modifier le type de collection de System.Array pour Generic List.

Cliquer sur Ok

Construire un client qui utilise un service avec l’entité Framework

Comme nous aurons probablement beaucoup de donnés à transférer nous devrons augmenter la taille maximale du buffer. Double-click sur app.config. Dans l’élément binding, ajouter/modifier l’attribut

MaxReceivedMessageSize. Augmenter sa valeur. Faire la même chose avec l’attribut MaxBufferSize. Les deux attributs MaxReceivedMessageSize et

MaxBufferSize doivent avoir la même valeur.

Construire un client qui utilise un service avec l’entité Framework

Maintenant, vous pouvez tester votre service en créant un objet en lien avec le proxy.

Construire un client qui utilise un service avec l’entité Framework

Faite les exercices.

Exercice

Questions?

Recommended