Bonjour,
J'aurais besoin de vos conseils pour l'architecture d'un petit module de recherche d'une application.
L'application est en SL3 avec service WCF.
Le service principale permet de retourner le résultat d'une recherche sur une BDD avec un mot clés passés en paramètre.
Or cette requête peut être très longue, il a été prévue de pouvoir l'annuler.
Dans nous avons un dictionnaire qui contient des références vers tous les SqlCommand lancé indexé par un GUID.
Voici le paramètrage du binding:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 <bindings> <customBinding> <binding name="customBinding0"> <binaryMessageEncoding/> <httpTransport/> </binding> </customBinding> </bindings> <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/> <services> <service behaviorConfiguration="FTS.Web.ServiceDBBehavior" name="FTS.Web.ServiceDB"> <endpoint address="" binding="customBinding" bindingConfiguration="customBinding0" contract="FTS.Web.ServiceDB"/> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </service> <service behaviorConfiguration="FTS.Web.ServiceTESTBehavior" name="FTS.Web.ServiceTEST"> <endpoint address="" binding="wsHttpBinding" contract="FTS.Web.IServiceTEST"> <identity> <dns value="localhost"/> </identity> </endpoint> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> </service> </services>
Voici le code du service WCF :
Le problème est le suivant lors de l'appel de la méthode Recherche(), il faudrait pouvoir renvoyer coté client le GUID dés que la commande SQL est lancé.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 { [ServiceContract(Namespace = ""] [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] public class ServiceDB { public static Dictionary<string, SqlCommand> dictionnaireGuid = new Dictionary<string, SqlCommand>(); [OperationContract] public List<string> GetDataAsynchrone(string texteRecherche) { List<string> resultatsTrouves = new List<string>(); using (SqlConnection myConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["connexionDevinfo"].ConnectionString)) /* Instance "à durée de vie limitée" de l'objet de connexion à la DB */ { try { myConnection.Open(); /* Connexion à la base de données */ /* Création de la requête de recherche */ //using (SqlCommand cmd = new SqlCommand("SELECT title FROM dbo.docs WHERE CONTAINS(*,'FORMSOF(INFLECTIONAL," + texteRecherche + ")')", myConnection)) using (SqlCommand cmd = new SqlCommand("requeteRalentie", myConnection)) { cmd.CommandType = System.Data.CommandType.StoredProcedure; // La commande est de type procédure stockée string guidCmd = Guid.NewGuid().ToString(); // On génère un guid qu'on passe en string dictionnaireGuid.Add(guidCmd, cmd); // On rajoute dans le dictionnaire la commande avec son guid IAsyncResult resultatAsyncResult = cmd.BeginExecuteReader(); /* Lancement de l'execution de la requête et récupération au format IAsyncResult */ [...] // Vérifie si le bouton d'annulation a été pressé. Initialisée à CancelButtonPressed, soit false // Tant que la récupération des résultats n'est pas terminée et que le bouton annuler n'a pas été pressé while (!resultatAsyncResult.IsCompleted) using (SqlDataReader resultatDataReader = cmd.EndExecuteReader(resultatAsyncResult)) // On récupère le jeu de résultats qu'on met dans un SqlDataReader { while (resultatDataReader.Read()) // Pour chaque ligne du SqlDataReader { [...] // On l'ajoute dans la liste de résultats au format List<string> } } } /* On dispose de cmd */ } catch (Exception e) /* En cas d'erreur de tout type */ { resultatsTrouves.Add(String.Format("Erreur : {0}", e.Message)); /* Affichage du message d'erreur */ } finally /* Qu'il y ait eu une erreur ou non */ { myConnection.Close(); /* Fermeture de la connexion */ } } /* Fin du using, on dispose de myConnexion */ return resultatsTrouves; } /// <summary> /// Kill la commande identifiée par le guid indiqué /// </summary> /// <param name="guid">Identifiant de la commande qui doit être annulée</param> [OperationContract] public void annulerCommande(string guid) // argument a remplacer après le tests : string guid { try { dictionnaireGuid[guid].Cancel(); // On annule la commande définie par le guid indiqué dictionnaireGuid.Remove(guid); // On retire la commande et son guid du dictionnaire } catch (Exception e) /* En cas d'erreur de tout type */ { } }
Est-ce qu'il est possible de créer un nouvelle événement sur le proxy ? Du genre GuidReceived ?
Est-ce qu'il faut passer par du full duplex ? si oui comment le faire avec quel binding.
Partager