Mim

Select * from Seb where Sujets in (SQL Server 2008, ADO.NET, Visual Studio 2008)

juillet 2008 - Messages

Sync Services : Client Sql Server Express

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 Smile

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)
    • Récupère les changements survenus sur la source de données client.
  • public override SyncAnchor GetTableReceivedAnchor(string tableName)
    • Récupère la dernière ancre générée de la table paramètre 
      (pour rappel l'ancre étant une données unique identifiant dans
      le temps, le dernier changement survenu sur une table)
  • 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)
    • Ecrit un ancre de dernière modification dans la source de données, 
      pour une table donnée
  • public override void SetTableSentAnchor(string tableName, 
    SyncAnchor anchor)
    • Ecrit un ancre de dernier envoi dans la source de données, 
      pour une table donnée

 

N'hésiter pas à récupérer ce petit exemple d'implémentation qui s'avère, au final, plutôt simple !

Max(), Dbcc CheckIdent(), Ident_Current()

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 :

  1. IDENT_CURRENT() : Récupère la dernière valeur générée d'une colonne identité.

  2. IDENT_SEED() : Récupère la valeur de départ d'une colonne identité.

  3. 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
 
Ident_current 
 

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... Big GrinParty

 
WCF WPF ObjectDataProvider MaxConcurrentSessions

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 :

 

image

 

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 Winking