Partager via


Recevoir des messages fortement typés basés sur des données d’interrogation modifiées à partir de SQL Server à l’aide d’un modèle de service WCF

Vous pouvez configurer l’adaptateur SQL pour recevoir des messages d’interrogation fortement typés de SQL Server. Vous pouvez spécifier une instruction d’interrogation que l’adaptateur exécute pour interroger la base de données. L’instruction d’interrogation peut être une instruction SELECT ou une procédure stockée qui retourne un jeu de résultats. Vous devez utiliser l’interrogation fortement typée dans un scénario où vous souhaitez recevoir un jeu de résultats fortement typé. Pour plus d’informations sur la façon dont l’adaptateur prend en charge l’interrogation fortement typée, consultez Prise en charge des appels entrants à l’aide de l’interrogation.

Important

Si vous souhaitez avoir plusieurs opérations d’interrogation dans une seule application, vous devez spécifier une propriété de connexion InboundID dans le cadre de l’URI de connexion pour la rendre unique. L’ID entrant que vous spécifiez est ajouté à l’espace de noms d’opération pour le rendre unique.

Comment cette rubrique illustre l’interrogation

Dans cette rubrique, pour montrer comment l’adaptateur SQL prend en charge la réception de messages de modification de données fortement typés, créez une application .NET et générez le contrat de service WCF pour l’opération TypedPolling . Veillez à spécifier les éléments suivants lors de la génération du contrat de service WCF :

  • Vous devez spécifier un InboundID dans le cadre de l’URI de connexion.

  • Vous devez spécifier une instruction d’interrogation pour la propriété de liaison PollingStatement .

    En outre, si vous souhaitez spécifier d’autres propriétés de liaison associées à l’interrogation lors de la génération de la classe proxy, spécifiez polledDataAvailableStatement comme suit :

SELECT COUNT(*) FROM Employee

PolledDataAvailableStatement doit retourner un jeu de résultats avec la première cellule contenant une valeur positive. Si la première cellule ne contient pas de valeur positive, l’adaptateur n’exécute pas l’instruction d’interrogation.

Dans le cadre de l’instruction d’interrogation, effectuez les opérations suivantes :

  1. Sélectionnez toutes les lignes de la table Employee.

  2. Exécutez une procédure stockée (MOVE_EMP_DATA) pour déplacer tous les enregistrements de la table Employee vers une table EmployeeHistory.

  3. Exécutez une procédure stockée (ADD_EMP_DETAILS) pour ajouter un nouvel enregistrement à la table Employee. Cette procédure prend le nom, la désignation et le salaire de l’employé comme paramètres.

    Pour effectuer ces opérations, vous devez spécifier ce qui suit pour la propriété de liaison PollingStatement lors de la génération du contrat de service WCF et des classes d’assistance :

SELECT * FROM Employee;EXEC MOVE_EMP_DATA;EXEC ADD_EMP_DETAILS John, Tester, 100000

Une fois l’instruction d’interrogation exécutée, tous les enregistrements de la table Employee sont sélectionnés et le message de SQL Server est reçu. Une fois la procédure stockée MOVE_EMP_DATA exécutée par l’adaptateur, tous les enregistrements sont déplacés vers la table EmployeeHistory. Ensuite, la procédure stockée ADD_EMP_DETAILS est exécutée pour ajouter un nouvel enregistrement à la table Employee. L’exécution d’interrogation suivante ne retournera qu’un seul enregistrement. Ce cycle se poursuit jusqu’à ce que vous fermez l’hôte de service.

Configuration de l’interrogation typée avec les propriétés de liaison de l’adaptateur SQL

Le tableau suivant récapitule les propriétés de liaison de l’adaptateur SQL que vous utilisez pour configurer l’adaptateur pour recevoir des messages de modification de données. Outre la propriété de liaison PollingStatement , toutes les autres propriétés de liaison répertoriées dans cette section sont requises lors de l’exécution de l’application .NET. Vous devez spécifier la propriété de liaison PollingStatement avant de générer l’opération TypedPolling du contrat de service WCF.

Binding, propriété Description
InboundOperationType Spécifie si vous souhaitez effectuer une opération d’interrogation, de typedPolling ou de notification entrante. La valeur par défaut est Interrogation. Pour recevoir des messages d’interrogation fortement typés, définissez-le sur TypedPolling.
PolledDataAvailableStatement Spécifie l’instruction SQL que l’adaptateur exécute pour déterminer si des données sont disponibles pour l’interrogation. L’instruction SQL doit retourner un jeu de résultats composé de lignes et de colonnes. Uniquement si une ligne est disponible, l’instruction SQL spécifiée pour la propriété de liaison PollingStatement est exécutée.
PollingIntervalInSeconds Spécifie l’intervalle, en secondes, auquel l’adaptateur SQL exécute l’instruction spécifiée pour la propriété de liaison PolledDataAvailableStatement . La valeur par défaut est 30 secondes. L’intervalle d’interrogation détermine l’intervalle de temps entre les sondages successifs. Si l’instruction est exécutée dans l’intervalle spécifié, l’adaptateur attend le temps restant dans l’intervalle.
PollingStatement Spécifie l’instruction SQL pour interroger la table de base de données SQL Server. Vous pouvez spécifier une instruction SELECT simple ou une procédure stockée pour l’instruction d’interrogation. La valeur par défaut est null. Vous devez spécifier une valeur pour PollingStatement afin d’activer l’interrogation. L’instruction d’interrogation est exécutée uniquement s’il existe des données disponibles pour l’interrogation, qui sont déterminées par la propriété de liaison PolledDataAvailableStatement . Vous pouvez spécifier n’importe quel nombre d’instructions SQL séparées par un point-virgule. Important: Pour TypedPolling, vous devez spécifier cette propriété de liaison avant de générer des métadonnées.
PollWhileDataFound Spécifie si l’adaptateur SQL ignore l’intervalle d’interrogation et exécute en continu l’instruction SQL spécifiée pour la propriété de liaison PolledDataAvailableStatement , si des données sont disponibles dans la table interrogée. Si aucune donnée n’est disponible dans la table, l’adaptateur revient à exécuter l’instruction SQL à l’intervalle d’interrogation spécifié. La valeur par défaut est false.

Pour obtenir une description plus complète de ces propriétés, consultez En savoir plus sur les propriétés de liaison de l’adaptateur BizTalk pour SQL Server. Pour obtenir une description complète de l’utilisation de l’adaptateur SQL pour interroger SQL Server, lisez plus loin.

Configurer l’interrogation fortement typée dans le modèle de service WCF

Pour recevoir l’opération d’interrogation lorsque vous utilisez le modèle de service WCF, vous devez :

  1. Générez un contrat de service WCF (interface) pour l’opération TypedPolling à partir des métadonnées exposées par l’adaptateur. Pour ce faire, vous pouvez utiliser le plug-in Visual Studio Add Adapter Service Reference. Lors de la génération du contrat de service WCF pour cet exemple, vérifiez que :

    • Vous spécifiez l’InboundID en tant qu’employé.

    • Vous spécifiez une instruction d’interrogation pour la propriété de liaison PollingStatement . Pour cet exemple, spécifiez l’instruction d’interrogation comme suit :

      SELECT * FROM Employee;EXEC MOVE_EMP_DATA;EXEC ADD_EMP_DETAILS John, Tester, 100000
      
  2. Implémentez un service WCF à partir de cette interface.

  3. Hébergez ce service WCF à l’aide d’un hôte de service (System.ServiceModel.ServiceHost).

À propos des exemples utilisés dans cette rubrique

Les exemples de cette rubrique interrogent la table Employee. L’exemple utilise également la procédure stockée MOVE_EMP_DATA et ADD_EMP_DETAILS. Un script pour générer ces artefacts est fourni avec les exemples. Pour plus d’informations sur les exemples, consultez Exemples pour l’adaptateur SQL. Un exemple, TypedPolling_ServiceModel, basé sur cette rubrique, est également fourni avec les exemples d’adaptateur SQL.

Contrat et classe de service WCF

Vous pouvez utiliser le plug-in Add Adapter Service Reference pour créer un contrat de service WCF (interface) et des classes de prise en charge pour l’opération TypedPolling . Pour plus d’informations sur la génération d’un contrat de service WCF, consultez Générer un client WCF ou un contrat de service WCF pour SQL Server Artefacts.

Contrat de service WCF (interface)

Le code suivant montre le contrat de service WCF (interface) généré pour l’opération TypedPolling .

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://schemas.microsoft.com/Sql/2008/05/", ConfigurationName="TypedPolling_Employee")]
public interface TypedPolling_Employee {

    // CODEGEN: Generating message contract since the wrapper namespace (https://schemas.microsoft.com/Sql/2008/05/TypedPolling/Employee) of message TypedPolling
    // does not match the default value (https://schemas.microsoft.com/Sql/2008/05/)
    [System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="TypedPolling")]
    void TypedPolling(TypedPolling request);
}

Contrats de message

L’espace de noms de contrat de message est modifié par le paramètre InboundID dans l’URI de connexion, si spécifié. Dans cet exemple, vous avez spécifié l’ID entrant en tant qu’employé. Le message de demande retourne un jeu de résultats fortement typé.

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="TypedPolling", WrapperNamespace="http://schemas.microsoft.com/Sql/2008/05/TypedPolling/Employee", IsWrapped=true)]
public partial class TypedPolling {

[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/Sql/2008/05/TypedPolling/Employee", Order=0)]
    public schemas.microsoft.com.Sql._2008._05.TypedPolling.Employee.TypedPollingResultSet0[] TypedPollingResultSet0;

[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/Sql/2008/05/TypedPolling/Employee", Order=1)]
    public schemas.microsoft.com.Sql._2008._05.TypedPolling.Employee.TypedPollingResultSet1[] TypedPollingResultSet1;

    public TypedPolling() {
    }

    public TypedPolling(schemas.microsoft.com.Sql._2008._05.TypedPolling.Employee.TypedPollingResultSet0[] TypedPollingResultSet0, schemas.microsoft.com.Sql._2008._05.TypedPolling.Employee.TypedPollingResultSet1[] TypedPollingResultSet1) {
        this.TypedPollingResultSet0 = TypedPollingResultSet0;
        this.TypedPollingResultSet1 = TypedPollingResultSet1;
    }
}

Classe de service WCF

Le plug-in Add Adapter Service Reference génère également un fichier qui a un stub pour la classe de service WCF implémentée à partir du contrat de service (interface). Le nom du fichier est SqlAdapterBindingService.cs. Vous pouvez insérer la logique pour traiter l’opération TypedPolling directement dans cette classe. Le code suivant montre la classe de service WCF générée par le plug-in Add Adapter Service Reference.

namespace SqlAdapterBindingNamespace {

    public class SqlAdapterBindingService : TypedPolling_Employee {

        // CODEGEN: Generating message contract since the wrapper namespace (https://schemas.microsoft.com/Sql/2008/05/TypedPolling/Employee) of message TypedPolling
        // does not match the default value (https://schemas.microsoft.com/Sql/2008/05/)
        public virtual void TypedPolling(TypedPolling request) {
            throw new System.NotImplementedException("The method or operation is not implemented.");
        }
    }
}

Recevoir des messages entrants fortement typés pour l’opération d’interrogation

Cette section fournit des instructions sur l’écriture d’une application .NET pour recevoir des messages d’interrogation entrants fortement typés à l’aide de l’adaptateur SQL.

  1. Utilisez le plug-in Add Adapter Service Reference pour générer un contrat de service WCF (interface) et des classes d’assistance pour l’opération TypedPolling . Veillez à spécifier ce qui suit lors de la génération du contrat de service WCF pour cet exemple :

    • Vous devez spécifier l’InboundID comme Employee.

    • Vous devez spécifier une instruction d’interrogation pour la propriété de liaison PollingStatement . Pour cet exemple, spécifiez l’instruction d’interrogation comme suit :

      SELECT * FROM Employee;EXEC MOVE_EMP_DATA;EXEC ADD_EMP_DETAILS John, Tester, 100000
      

      Pour plus d’informations, consultez Générer un client WCF ou un contrat de service WCF pour SQL Server Artefacts. Vous pouvez éventuellement spécifier les propriétés de liaison lors de la génération du contrat de service et des classes d’assistance. Cela garantit qu’ils sont correctement définis dans le fichier de configuration généré.

  2. Implémentez un service WCF à partir des classes d’interface et d’assistance générées à l’étape 1. La méthode TypedPolling de cette classe peut lever une exception pour annuler la transaction d’interrogation si une erreur est rencontrée lors du traitement des données reçues de l’opération TypedPolling ; sinon, la méthode ne retourne rien. Vous devez attribuer la classe de service WCF comme suit :

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    

    Dans la méthode TypedPolling , vous pouvez implémenter directement votre logique d’application. Cette classe se trouve dans SqlAdapterBindingService.cs. Ce code dans cet exemple sous-classe la classe SqlAdapterBindingService . Dans ce code, le message d’interrogation reçu en tant que jeu de résultats fortement typé est écrit dans la console.

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    
    public class PollingService : SqlAdapterBindingNamespace.SqlAdapterBindingService
    {
        public override void TypedPolling(TypedPolling request)
        {
            Console.WriteLine("\nNew Polling Records Received");
            Console.WriteLine("*************************************************");
            Console.WriteLine("Employee ID\tName\tDesignation\tSalary");
    
            for (int i = 0; i < request.TypedPollingResultSet0.Length; i++)
            {
                Console.WriteLine("{0}\t{1}\t{2}\t{3}",
                request.TypedPollingResultSet0[i].Employee_ID,
                request.TypedPollingResultSet0[i].Name,
                request.TypedPollingResultSet0[i].Designation,
                request.TypedPollingResultSet0[i].Salary);
            }
            Console.WriteLine("*************************************************");
            Console.WriteLine("\nHit <RETURN> to stop polling");
        }
    }
    
  3. Étant donné que l’adaptateur SQL n’accepte pas les informations d’identification dans le cadre de l’URI de connexion, vous devez implémenter la classe suivante pour transmettre les informations d’identification pour la base de données SQL Server. Dans la dernière partie de l’application, vous allez instancier cette classe pour transmettre les informations d’identification SQL Server.

    class PollingCredentials : ClientCredentials, IServiceBehavior
    {
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {
            bindingParameters.Add(this);
        }
    
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        { }
    
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        { }
    
        protected override ClientCredentials CloneCore()
        {
            ClientCredentials clone = new PollingCredentials();
            clone.UserName.UserName = this.UserName.UserName;
            clone.UserName.Password = this.UserName.Password;
            return clone;
        }
    }
    
  4. Créez un SqlAdapterBinding et configurez l’opération d’interrogation en spécifiant les propriétés de liaison. Vous pouvez effectuer cette opération de manière explicite dans le code ou de manière déclarative dans la configuration. Au minimum, vous devez spécifier InboundOperationType, PolledDataAvailableStatement et PollingStatement.

    SqlAdapterBinding binding = new SqlAdapterBinding();
    binding.InboundOperationType = InboundOperation.TypedPolling;
    binding.PolledDataAvailableStatement = "SELECT COUNT (*) FROM EMPLOYEE";
    binding.PollingStatement = "SELECT * FROM Employee;EXEC MOVE_EMP_DATA;EXEC ADD_EMP_DETAILS John, Tester, 100000";
    
  5. Spécifiez SQL Server informations d’identification de base de données en instanciant la classe PollingCredentials que vous avez créée à l’étape 3.

    PollingCredentials credentials = new PollingCredentials();
    credentials.UserName.UserName = "<Enter user name here>";
    credentials.UserName.Password = "<Enter password here>";
    
  6. Créez une instance du service WCF créé à l’étape 2.

    // create service instance
    PollingService service = new PollingService();
    
  7. Créez un instance de System.ServiceModel.ServiceHost à l’aide du service WCF et d’un URI de connexion de base. L’URI de connexion de base ne peut pas contenir l’ID entrant. Vous devez également spécifier les informations d’identification ici.

    // Enable service host
    Uri[] baseUri = new Uri[] { new Uri("mssql://mysqlserver//mydatabase") };
    ServiceHost serviceHost = new ServiceHost(service, baseUri);
    serviceHost.Description.Behaviors.Add(credentials);
    
    
  8. Ajoutez un point de terminaison de service à l’hôte de service. Pour ce faire :

    • Utilisez la liaison créée à l’étape 4.

    • Spécifiez un URI de connexion qui contient des informations d’identification et, si nécessaire, un ID entrant.

    • Spécifiez le contrat comme « TypedPolling_Employee ».

    // Add service endpoint: be sure to specify TypedPolling_Employee as the contract
    Uri ConnectionUri = new Uri("mssql://mysqlserver//mydatabase?InboundID=Employee");
    serviceHost.AddServiceEndpoint("TypedPolling_Employee", binding, ConnectionUri);
    
  9. Pour recevoir des données d’interrogation, ouvrez l’hôte de service. L’adaptateur retourne des données chaque fois que la requête retourne un jeu de résultats.

    // Open the service host to begin polling
    serviceHost.Open();
    
  10. Pour mettre fin à l’interrogation, fermez l’hôte de service.

    Important

    L’adaptateur continue d’interroger jusqu’à ce que l’hôte de service soit fermé.

    serviceHost.Close();
    

Exemple

L’exemple suivant montre une requête d’interrogation qui exécute la table Employee. L’instruction d’interrogation effectue les tâches suivantes :

  1. Sélectionne tous les enregistrements de la table Employee.

  2. Exécute la procédure stockée MOVE_EMP_DATA pour déplacer tous les enregistrements de la table Employee vers la table EmployeeHistory.

  3. Exécute la procédure stockée ADD_EMP_DETAILS pour ajouter un enregistrement unique à la table Employee.

    Le premier message d’interrogation contiendra tous les enregistrements de la table Employee. Les messages d’interrogation suivants ne contiennent que le dernier enregistrement inséré par la procédure stockée ADD_EMP_DETAILS. L’adaptateur continue d’interroger jusqu’à ce que vous fermez l’hôte de service en appuyant sur <RETURN>.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Adapters.Sql;
using Microsoft.ServiceModel.Channels;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using System.Collections.ObjectModel;

namespace TypedPolling_ServiceModel
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

    public class PollingService : SqlAdapterBindingNamespace.SqlAdapterBindingService
    {
        public override void TypedPolling(TypedPolling request)
        {
            Console.WriteLine("\nNew Polling Records Received");
            Console.WriteLine("*************************************************");
            Console.WriteLine("Employee ID\tName\tDesignation\tSalary");

            for (int i = 0; i < request.TypedPollingResultSet0.Length; i++)
            {
                Console.WriteLine("{0}\t{1}\t{2}\t{3}",
                request.TypedPollingResultSet0[i].Employee_ID,
                request.TypedPollingResultSet0[i].Name,
                request.TypedPollingResultSet0[i].Designation,
                request.TypedPollingResultSet0[i].Salary);
            }
            Console.WriteLine("*************************************************");
            Console.WriteLine("\nHit <RETURN> to stop polling");
        }
    }

    class PollingCredentials : ClientCredentials, IServiceBehavior
    {
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {
            bindingParameters.Add(this);
        }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        { }

        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        { }

        protected override ClientCredentials CloneCore()
        {
            ClientCredentials clone = new PollingCredentials();
            clone.UserName.UserName = this.UserName.UserName;
            clone.UserName.Password = this.UserName.Password;
            return clone;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            ServiceHost serviceHost = null;
            try
            {
                Console.WriteLine("Sample started...");
                Console.WriteLine("Press any key to start polling...");
                Console.ReadLine();

                SqlAdapterBinding binding = new SqlAdapterBinding();
                binding.InboundOperationType = InboundOperation.TypedPolling;
                binding.PolledDataAvailableStatement = "SELECT COUNT (*) FROM EMPLOYEE";
                binding.PollingStatement = "SELECT * FROM Employee;EXEC MOVE_EMP_DATA;EXEC ADD_EMP_DETAILS John, Tester, 100000";
                Console.WriteLine("Binding properties assigned...");

                // This URI is used to specify the address for the ServiceEndpoint
                // It must contain the InboundId that was used to generate
                // the WCF service callback interface
                Uri ConnectionUri = new Uri("mssql://mysqlserver//mydatabase?InboundId=Employee");

                // This URI is used to initialize the ServiceHost. It cannot contain
                // the InboundID; otherwise,an exception is thrown when
                // the ServiceHost is initialized.
                Uri[] baseUri = new Uri[] { new Uri("mssql://mysqlserver//mydatabase") };

                PollingCredentials credentials = new PollingCredentials();
                credentials.UserName.UserName = "<Enter user name here>";
                credentials.UserName.Password = "<Enter password here>";

                Console.WriteLine("Opening service host...");
                PollingService service = new PollingService();
                serviceHost = new ServiceHost(service, baseUri);
                serviceHost.Description.Behaviors.Add(credentials);
                serviceHost.AddServiceEndpoint("TypedPolling_Employee", binding, ConnectionUri);
                serviceHost.Open();
                Console.WriteLine("Service host opened...");
                Console.WriteLine("Polling started...");
                Console.ReadLine();
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception :" + e.Message);
                Console.ReadLine();

                /* If there is an error it will be specified in the inner exception */
                if (e.InnerException != null)
                {
                    Console.WriteLine("InnerException: " + e.InnerException.Message);
                    Console.ReadLine();
                }
            }
            finally
            {
                // IMPORTANT: you must close the ServiceHost to stop polling
                if (serviceHost.State == CommunicationState.Opened)
                    serviceHost.Close();
                else
                    serviceHost.Abort();
            }
        }
    }
}

Voir aussi

Interroger SQL Server à l’aide de l’adaptateur SQL avec le modèle de service WCF