Traduction

Cet article est la traduction la plus fidèle possible de l'article original de Brad Abrams, Business Apps Example for Silverlight 3 RTM and .NET RIA Services July Update: Part 17: Evolving an application.

Article

Voilà encore des choses tirées de ma présentation du Mix09 "Building business applications with Silverlight 3". Jusqu'ici, dans cette série, nous avons vu comment créer une nouvelle application en utilisant Silverlight 3 et .NET RIA Services. Mais voyons maintenant comment faire évoluer une application SL3/RIA Services existante. Après tout, pour la plupart d'entre nous, c'est notre travail quotidien. Il est rare d'avoir l'occasion de commencer à partir de rien une application sur laquelle on a tout contrôle. La possibilité de gérer la maintenance d'une application permet à un framework de passer du statut de "super jouet de démo" à celui d'outil important.

Pour le contexte, vous pouvez regarder la vidéo originale de la session complète, et lire le reste de la série.

Cette démo nécessite les éléments suivants (tout est 100 % gratuit) :

  • Visual Studio 2008 SP1 (qui inclut SQL Server Express 2008) ;
  • Silverlight 3 RTM ;
  • .NET RIA Services July '09 Preview.

Téléchargez aussi les fichiers de la démo complète.

Dans cette partie, nous allons étudier quelques évolutions intéressantes de l'application SuperEmployee que nous étions en train de développer. La première est d'ajouter une nouvelle colonne dans la table sur laquelle nous avons travaillé, et la seconde est d'ajouter une nouvelle table avec des données supplémentaires associées à chaque SuperEmployee.

Une bonne partie des détails du flux de travail pour cette évolution dépend de la DAL (couche d'accès aux données, NdT) que vous utilisez. Puisque .NET RIA Services n'est pas dépendant d'une DAL spécifique, cette partie de l'évolution peut varier un peu. Pour ce tutoriel pas à pas, je vous montrerai comment ça se passe avec Entity Framework et je vous laisserai le soin de l'adapter à votre propre DAL.

Ajout d'une nouvelle colonne

Depuis que j'ai créé le schéma de la table SuperEmployee il y a six mois, je trouve qu'il manque vraiment l'aspect le plus important d'un superhéros : savoir quel est son pouvoir. Je veux dire, je dois connaitre leur superpouvoir pour les embaucher, n'est-ce pas ? Voyons donc comment ajouter le superpouvoir à la base de données.

Ouvrons la base Northwind.mdf depuis le répertoire App_Data et sélectionnons "Ouvrir la définition de table" :

Image non disponible

Ajoutons ensuite une colonne appelée "SuperPower" et définissons-la comme étant de type nvarchar(MAX).

Image non disponible

Voilà, nous avons mis à jour le schéma de la base, il faut maintenant mettre à jour le modèle. Pour ce faire, ouvrez Nortwind.edmx et sélectionnez "Mettre à jour le modèle à partir de la base de données" :

Image non disponible

Sélectionnez "Actualiser" :

Image non disponible

Et on voit que notre modèle est mis à jour !

Image non disponible

Maintenant, recompilons simplement le projet, et nous pouvons accéder à cette nouvelle propriété à partir du serveur Web dans le DomainService si nous voulons écrire de la logique d'application qui l'utilise, sinon nous pouvons y accéder directement à partir du client.

Image non disponible

Pour commencer, ajoutons SuperPower à la liste des champs que le DataForm gère pour nous. C'est juste une mise à jour sur le DataForm dont nous avons parlé dans la partie 2 : Rich Data Query .

 
Sélectionnez

<dataControls:DataField>

   <TextBox Text="{Binding SuperPower, Mode=TwoWay}" />

</dataControls:DataField>

Et bien sûr l'affichage marche très bien :

Image non disponible

Et je peux maintenant ajouter un superpouvoir à plusieurs superhéros et valider pour voir les changements répercutés sur la base de données :

Image non disponible

Ajoutons maintenant juste un peu de validation à notre nouveau membre. Dans le fichier SuperEmployeeDomainService.metadata.cs, ajoutez :

 
Sélectionnez

[StringLength(25,MinimumLength=3,
   ErrorMessage = "Superpower's should be between 3 and 25 characters long")]
public string SuperPower;

Compilez, exécutez, et nous avons maintenant la validation !

Image non disponible

Revenons à notre service Astoria et à notre client WinForm de la partie 5. Que devons-nous faire pour les mettre à jour ? Eh bien, pas grand-chose. Le service Astoria est généré dynamiquement à partir du modèle, et le DataGridView est aussi dynamique dans notre cas, donc tout ce qu'il y a à faire est de mettre à jour la référence de service, et le tour est joué !

Image non disponible

Et l'application fonctionne parfaitement. Un moyen facile de saisir beaucoup de données rapidement.

Image non disponible

J'ai montré jusqu'ici à quel point il est facile de faire évoluer une entité pour lui ajouter un champ supplémentaire. Voyons maintenant comment ajouter une nouvelle entité complète.

Ajout d'une nouvelle entité associée

Pour cet exemple, je vais ajouter les informations de contact de l'agent du superhéros pour pouvoir entrer en relation avec le superhéros qu'on décide d'embaucher. La première étape est d'ajouter une table à notre base de données pour stocker les informations de contact :

Image non disponible

Il faut ensuite l'associer à la table SuperEmployees via une clé étrangère.

Image non disponible

On peut maintenant mettre à jour notre modèle Entity Framework :

Image non disponible

On veut ajouter la nouvelle table Contact :

Image non disponible

On veut également mettre à jour notre classe SuperEmployee pour récupérer la clé étrangère pour le Contact :

Image non disponible

Cela nous donne ce modèle :

Image non disponible

Nous faisons une recompilation complète et tout devrait être bon.

Intégrons maintenant la table Contact à notre application.

Tout d'abord nous devons ajouter la logique à notre DomainService.

 
Sélectionnez

public IQueryable<SuperEmployee> GetSuperEmployees()
{
   return this.Context.SuperEmployeeSet
              .Include("Contact")
              .Where(emp=>emp.Issues>100)
              .OrderBy(emp=>emp.EmployeeID);
}

Remarquez qu'à la quatrième ligne, on a indiqué à Entity Framework d'inclure le Contact associé quand on récupère chaque SuperEmployee de la base de données.

Maintenant, dans SuperEmployeeMetadata.cs, il faut ajouter des métadonnées pour dire à RIA Services d'inclure les informations de contact dans les données qu'il envoie au client :

 
Sélectionnez

public void InsertContact(Contact contact)
{
   this.Context.AddToContact(contact);
}

public void UpdateContact(Contact currentContact)
{
   this.Context.AttachAsModified(currentContact,
                                 ChangeSet.GetOriginal(currentContact));
}

Super, la partie serveur est terminée, maintenant repassons au client. Ce que je veux faire ici, c'est ajouter un élément graphique au DataForm des détails pour afficher les informations de contact.

À l'intérieur du DataForm dans Home.xaml, ajoutons un bouton pour éditer les informations de contact :

 
Sélectionnez

<Button Content="Edit Contact Information..." 
       Width="205" Height="28"
       Margin="15,10,0,0" HorizontalAlignment="Left"
       Click="EditContact_Click" >
Image non disponible

Il faut maintenant gérer l'évènement Click du bouton. Ici on va créer une fenêtre enfant pour afficher un formulaire pour visualiser et modifier les informations de contact :

 
Sélectionnez

private void EditContact_Click(object sender, RoutedEventArgs e)
{
   var emp = dataForm1.CurrentItem as SuperEmployee;
   if (emp.Contact == null)
       emp.Contact = new Contact();
   var w = new EditContactWindow(emp.Contact);
   w.Show();
   w.Closed += EditContact_Closed;
}

void EditContact_Closed(object sender, EventArgs e)
{
   var win = sender as EditContactWindow;
   var emp = dataForm1.CurrentItem as SuperEmployee;
   if (win.DialogResult == true)
   {
       emp.Contact = win.Contact; 
   }
}

Ajoutez une nouvelle fenêtre enfant et appelez-la EditContactWindow. Voici son code-behind :

 
Sélectionnez

public partial class EditContactWindow : ChildWindow
{
   public Contact Contact;
   public EditContactWindow(Contact contact)
   {
       InitializeComponent();
       Contact = contact;
       this.LayoutRoot.DataContext = Contact; 
   }

   private void OKButton_Click(object sender, RoutedEventArgs e)
   {
       this.DialogResult = true;
       dataform1.CommitEdit();
   }

   private void CancelButton_Click(object sender, RoutedEventArgs e)
   {
       this.DialogResult = false;
   }
}

Et le XAML est simplement un DataForm pour afficher les données :

 
Sélectionnez

<dataFormToolkit:DataForm   x:Name="dataform1" CurrentItem="{Binding}">
   <dataControls:DataForm.EditTemplate>
       <DataTemplate>
           <StackPanel>
               <dataControls:DataField>
                   <TextBox Text="{Binding ContactName, Mode=TwoWay}" />
               </dataControls:DataField>
               <dataControls:DataField>
                   <TextBox Text="{Binding ContactTitle, Mode=TwoWay}" />
               </dataControls:DataField>
               <dataControls:DataField>
                   <TextBox Text="{Binding Address, Mode=TwoWay}" />
               </dataControls:DataField>
               <dataControls:DataField>
                   <TextBox Text="{Binding City, Mode=TwoWay}" />
               </dataControls:DataField>
               <dataControls:DataField>
                   <TextBox Text="{Binding Region, Mode=TwoWay}" />
               </dataControls:DataField>
               <dataControls:DataField>
                   <TextBox Text="{Binding PostalCode, Mode=TwoWay}" />
               </dataControls:DataField>
               <dataControls:DataField>
                   <TextBox Text="{Binding Phone, Mode=TwoWay}" />
               </dataControls:DataField>
           </StackPanel>
       </DataTemplate>
   </dataControls:DataForm.EditTemplate>
</dataFormToolkit:DataForm>

Et le résultat est magnifique !

Image non disponible

Remarquez que côté serveur, dans SuperEmployeeDomainService.metadata.cs, j'ai précisé des métadonnées pour contrôler comment le contact est affiché. C'est aussi là que je mettrais les paramètres de validation.

 
Sélectionnez

[MetadataTypeAttribute(typeof(Contact.ContactMetadata))]
public partial class Contact
{
   internal sealed class ContactMetadata
   {
       // Metadata classes are not meant to be instantiated.
       private ContactMetadata()
       {
       }

       [Display(Name="Name")]
       public object ContactName;

       [Display(Name = "Title")]
       public object ContactTitle;

       public object Address;

       public object City;

       [Display(Name = "State")]
       public object Region;

       [Display(Name = "Zip Code")]
       public object PostalCode;

       public object Phone;
   }

}

C'est fini !

Dans cette partie nous avons vu comment faire évoluer petit à petit une application RIA Services + Silverlight. J'ai montré comment ajouter une nouvelle colonne à une table existante et comment ajouter une nouvelle table.

Profitez-en !

Conclusion

Ceci conclut la dix-septième partie de cette série. La partie suivante traitera des fournisseurs Linq personnalisé.

Remerciements

Je tiens ici à remercier Brad Abrams pour nous avoir autorisé à traduire son article.
Je remercie également ClaudeLELOUP et jacques_jean pour leur relecture et leurs propositions.