juillet 2008 - Messages
Beaucoup de personnes me demandent souvent s'il existe le provider client Sync Services pour SQL Server Express.
Pour rappel, nativement, il existe le provider client Sql Server CE.
Et bien sachez qu'il existe maintenant ce fameux provider de synchronisation client, sous forme d'exemple !
Il n'est pas tout à fait complet mais reste une bonne base pour appréhender la création d'un fournisseur de synchronisation client 
Vous le trouverez ici à télécharger
Vous allez donc découvrir une classe qui hérite de ClientSyncProvider
public class SqlExpressClientSyncProvider : ClientSyncProvider
{
...
}
Cette classe doit implémenter différentes méthodes pour fonctionner, qui sont pour rappel :
-
public override SyncContext ApplyChanges(SyncGroupMetadata groupMetadata,
DataSet dataSet, SyncSession syncSession)
- Cette méthode applique les changements sur la source de données client.
-
public override SyncContext GetChanges(SyncGroupMetadata groupMetadata,
SyncSession syncSession)
-
public override SyncAnchor GetTableReceivedAnchor(string tableName)
- public override SyncAnchor GetTableSentAnchor(string tableName)
- Récupère la dernière ancre envoyée de la table paramètre
-
public override void SetTableReceivedAnchor(string tableName,
SyncAnchor anchor)
-
public override void SetTableSentAnchor(string tableName,
SyncAnchor anchor)
N'hésiter pas à récupérer ce petit exemple d'implémentation qui s'avère, au final, plutôt simple !
Rien à voir avec la choucroute, mais je rentre d'une semaine de vacances, et ben, ça fait du bien !
Evidemment, le retour aux sources est assez douloureux, surtout lorsqu'on doit dépiler les quantités de mails de retard (en virant les 90% de spam et autre bétises) et l'ensemble des flux RSS qu'on a l'habitude de parcourir !
Et justement, ce matin je suis tombé sur ce post intéressant où Pinal Dave nous explique comment récupérer la valeur courant d'un incrément automatique.
Bon pour faire simple; et comme il dit, y'a deux solutions :
1) la pas élégante (mais qui marche) :
use AdventureWorks
Select max(DatabaseLogID) From dbo.DatabaseLog as MaxErrorLog
2) la façon élégante et qui marche (aussi) :
useAdventureWorks
Dbcc CheckIdent('dbo.DatabaseLog');
Mais ... je vois un problème à la deuxième solution : Impossible de récupérer la valeur dans une application .Net ! (Là où c'est possible avec la première méthode)
heureusement, il existe une Troisième méthode qui va nous permettre de récupérer non seulement l'incrément en cours, mais aussi d'autres valeurs intéressantes comme le Seed par exemple:
Nous avons à notre disposition pas moins de 3 fonctions utiles :
-
IDENT_CURRENT() : Récupère la dernière valeur générée d'une colonne identité.
-
IDENT_SEED() : Récupère la valeur de départ d'une colonne identité.
-
IDENT_INCR() : Récupère l'incrément d'une colonne identité
Ce qui donne, par code un truc du genre :
Declare @tableName varchar(20) = 'dbo.DatabaseLog'
SELECT @tableName as [Table],
IDENT_SEED(@tableName) AS Seed,
IDENT_INCR(@tableName) AS Increment,
IDENT_CURRENT(@tableName) AS Current_Identity
Et là biensûr pas de problème particulier pour récupérer ces valeurs depuis du code .Net !
Ah là là, les vacances sont finies... 

Je viens de m'arracher la tête sur un vil bug impliquant WCF et WPF via l'ObjectDataProvider
Au bout de 10 appels de mon service (via le proxy généré avec un Add Service Reference) j'atteins le MaxConcurrentSessions, fixé de base à 10.
Le code serveur n'ayant rien d'extraordinaire, je passe directement à mon code client, dans mon formulaire WCF
ObjectDataProvider odpServiceType;
private void Window_Loaded(object sender, RoutedEventArgs e)
{
//Set source for service type
odpServiceType = new ObjectDataProvider();
// Make it Asynchronous
odpServiceType.IsAsynchronous = true;
odpServiceType.ObjectType = typeof(MyServiceProxy.MyServiceClient);
odpServiceType.MethodName = "GetServiceTypes";
// Set DataContext
this.comboBox1.DataContext = odpServiceType;
}
J'utilise mon ObjectDataProvider en lui précisant le type d'objet et la méthode à appeller.
Je lance l'application 10 fois, la 11eme se vautre lamentablement.
Hop un coup de Service Trace Viewer me donne vite l'indication que je cherche :
MaxConcurrentSessions atteint !!!
Et oui, l'objectdataprovider n'appelle pas explicitement le close de mon channel !
Résolution facile, enfin une fois qu'on a compris :)
Sur le Close de ma Window, nous castons l'instance crée par l'objectdataprovider en MyServiceClient, et nous appellons explicitement la méthode close:
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
MyServiceProxy.MyServiceClient service = odpServiceType.ObjectInstance
as MyServiceProxy.MyServiceClient;
if (service != null && service.State != CommunicationState.Closed)
service.Close();
base.OnClosing(e);
}
Bon WCF-WPF à tous 