Exemple d'application métier avec Silverlight 3 et .NET RIA Services - Partie 17 : Faire évoluer une application

| Brad Abrams | Thomas Levesque (Traduction) |

Cet article fait partie d'une série de traductions d'articles de Brad Abrams sur le développement d'applications métier avec Silverlight et .NET RIA Services.

Retrouvez l'ensemble des articles de la série sur cette page : Exemple d'application métier avec Silverlight 3 et .NET RIA Services.

Commentez cet article : Commentez ♪

- Titre : Exemple d'application métier avec Silverlight 3 et .NET RIA Services - Partie 17 : Faire évoluer une application

- Auteurs : Brad Abrams, Thomas Levesque (Traduction)

- Parution : 15 janvier 2011

- Licence : Copyright ® 2011 Brad Abrams. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- Traduction

- Article

- Ajout d'une nouvelle colonne

- Ajout d'une nouvelle entité associée

- Conclusion

- Remerciements

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 » :

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

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 » :

Sélectionnez « Actualiser » :

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

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.

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.

<dataControls:DataField>

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

</dataControls:DataField>

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

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 :

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

[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 !

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é !

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

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 :

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

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

On veut ajouter la nouvelle table Contact :

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

Cela nous donne ce modèle :

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.

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 :

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 :

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

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 :

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 :

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 :

<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 !

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.

[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 de nous avoir autorisés à traduire son article.
Je remercie également ClaudeLELOUP et jacques_jean pour leur relecture et leurs propositions.