In base al contenuto

Le informazioni contenute in questo argomento sono valide per Windows Workflow Foundation 4.

Quando i servizi flusso di lavoro comunicano con client e altri servizi, sono spesso presenti alcuni dati nei messaggi scambiati che correlano in modo univoco un messaggio a una particolare istanza. La correlazione basata sul contenuto utilizza questi dati nel messaggio, ad esempio un numero cliente o un ID dell'ordine, per indirizzare messaggi all'istanza del flusso di lavoro appropriata. In questo argomento viene illustrato come utilizzare la correlazione basata sul contenuto nei flussi di lavoro.

Utilizzo della correlazione basata sul contenuto

La correlazione basata sul contenuto viene utilizzata se un servizio flusso di lavoro dispone di più metodi a cui viene eseguito l'accesso da parte di un solo client e una parte dei dati nei messaggi scambiati identifica l'istanza desiderata.

Ee358755.note(it-it,VS.100).gifNota:
La correlazione basata sul contenuto risulta utile se non è possibile utilizzare la correlazione del contesto in quanto l'associazione non rientra tra quelle di scambio del contesto supportate. Per ulteriori informazioni su correlazione del contesto, vedere Scambio del contesto.

Ogni attività di messaggistica utilizzata in queste comunicazioni deve specificare il percorso dei dati nel messaggio che identificano in modo univoco l'istanza. A tale scopo viene fornito un elemento MessageQuerySet, che utilizza un elemento QueryCorrelationInitializer o CorrelatesOn, che esegue una query nel messaggio per una o più parti di dati che identificano in modo univoco l'istanza.

Ee358755.Warning(it-it,VS.100).gif Attenzione:
Per i dati utilizzati per identificare l'istanza viene generato un hash in una chiave di correlazione. È necessario verificare che i dati utilizzati per la correlazione siano univoci. In caso contrario si potrebbero verificare conflitti nella chiave con hash e i messaggi potrebbero essere indirizzati in modo errato. Una correlazione basata esclusivamente su un nome di cliente può ad esempio generare un conflitto, poiché possono esistere più clienti con lo stesso nome. Non utilizzare i due punti (:) come parte dei dati per correlare il messaggio, poiché vengono già utilizzati per delimitare il valore e la chiave della query del messaggio per formattare la stringa per la quale verrà generato un hash.

Nell'esempio seguente, l'elemento Receive/SendReply iniziale in un servizio flusso di lavoro restituisce un elementoOrderId che viene quindi passato nuovamente dal client sulla chiamata all'attività Receive seguente nel servizio flusso di lavoro.

Variable<string> OrderId = new Variable<string>();
Variable<string> Item = new Variable<string>();
Variable<CorrelationHandle> OrderIdHandle = new Variable<CorrelationHandle>();

Receive StartOrder = new Receive
{
    CanCreateInstance = true,
    ServiceContractName = "IOrderService",
    OperationName = "StartOrder"
};

SendReply ReplyToStartOrder = new SendReply
{
    Request = StartOrder,
    Content = SendParametersContent.Create(new Dictionary<string, InArgument>
        { { "OrderId", new InArgument<string>((env) => OrderId.Get(env)) } }),
    CorrelationInitializers =
    {
        new QueryCorrelationInitializer
        {
            CorrelationHandle = OrderIdHandle,
            MessageQuerySet = new MessageQuerySet
            {
                {
                    "OrderId", 
                    new XPathMessageQuery("sm:body()/tempuri:StartOrderResponse/tempuri:OrderId")
                }
            }
        }
    }
};

Receive AddItem = new Receive
{
    ServiceContractName = "IOrderService",
    OperationName = "AddItem",
    CorrelatesWith = OrderIdHandle,
    CorrelatesOn = new MessageQuerySet
    {
        {
            "OrderId", 
              new XPathMessageQuery("sm:body()/tempuri:AddItem/tempuri:OrderId")
        }
    },
    Content = ReceiveParametersContent.Create(new Dictionary<string, OutArgument>
        { { "OrderId", new OutArgument<string>(OrderId) },  
        { "Item", new OutArgument<string>(Item) } })
};

SendReply ReplyToAddItem = new SendReply
{
    Request = AddItem,
    Content = SendParametersContent.Create(new Dictionary<string, InArgument>
        { { "Reply", new InArgument<string>((env) => "Item added: " + Item.Get(env)) } }),
};

// Construct a workflow using StartOrder, ReplyToStartOrder, and AddItem.

Nell'esempio precedente viene mostrata una correlazione basata sul contenuto inizializzata da SendReply. MessageQuerySet specifica che i dati utilizzati per identificare i messaggi successivi a questo servizio sono di tipo OrderId.

SendReply ReplyToStartOrder = new SendReply
{
    Request = StartOrder,
    Content = SendParametersContent.Create(new Dictionary<string, InArgument>
        { { "OrderId", new InArgument<string>((env) => OrderId.Get(env)) } }),
    CorrelationInitializers =
    {
        new QueryCorrelationInitializer
        {
            CorrelationHandle = OrderIdHandle,
            MessageQuerySet = new MessageQuerySet
            {
                {
                    "OrderId", 
                    new XPathMessageQuery("sm:body()/tempuri:StartOrderResponse/tempuri:OrderId")
                }
            }
        }
    }
};

L'attività Receive che successiva a SendReply nel flusso di lavoro segue la correlazione inizializzata da SendReply. Entrambe le attività condividono lo stesso elemento CorrelationHandle, ma ognuna dispone di specifici elementi MessageQuerySet e XPathMessageQuery che indicano la posizione all'interno del messaggio in cui si trovano i dati di identificazione. Nell'attività che inizializza la correlazione, questo elemento MessageQuerySet viene specificato nella proprietà CorrelationInitializers e, per qualsiasi attività Receive successiva, mediante la proprietà CorrelatesOn.

Receive AddItem = new Receive
{
    ServiceContractName = "IOrderService",
    OperationName = "AddItem",
    CorrelatesWith = OrderIdHandle,
    CorrelatesOn = new MessageQuerySet
    {
        {
            "OrderId", 
              new XPathMessageQuery("sm:body()/tempuri:AddItem/tempuri:OrderId")
        }
    },
    Content = ReceiveParametersContent.Create(new Dictionary<string, OutArgument>
        { { "OrderId", new OutArgument<string>(OrderId) },  
        { "Item", new OutArgument<string>(Item) } })
};

Una correlazione basata sul contenuto può essere inizializzata da qualsiasi attività di messaggistica (Send, Receive, SendReply, ReceiveReply) quando i dati vengono propagati come parte di un messaggio. Se questa parte di dati non viene propagata come parte di un messaggio, è possibile inizializzarla in modo esplicito tramite l'attività InitializeCorrelation. Se sono necessarie più parti di dati per identificare in modo univoco il messaggio, è possibile aggiungere più query a MessageQuerySet. In questi esempi è stato fornito in modo esplicito un elemento CorrelationHandle a ogni attività che utilizza le proprietà CorrelatesWith o CorrelationHandle, ma se è necessaria una sola correlazione per l'intero flusso di lavoro intero, come in questo caso, in cui tutti gli elementi vengono correlati in OrderId, è sufficiente la gestione dell'handle di correlazione implicita fornita da WorkflowServiceHost.

Utilizzo dell'attività InitializeCorrelation

Nell'esempio precedente l'elemento OrderId è stato propagato al chiamante tramite l'attività SendReply e la correlazione è stata inizializzata in questo punto. È possibile ottenere lo stesso comportamento utilizzando l'attività InitializeCorrelation. L'attività InitializeCorrelation utilizza l'elemento CorrelationHandle e un dizionario di elementi che rappresentano i dati utilizzati per eseguire il mapping del messaggio all'istanza corretta. Per utilizzare l'attività InitializeCorrelation nell'esempio precedente, rimuovere CorrelationInitializers dall'attività SendReply e inizializzare la correlazione utilizzando l'attività InitializeCorrelation.

Variable<string> OrderId = new Variable<string>();
Variable<string> Item = new Variable<string>();
Variable<CorrelationHandle> OrderIdHandle = new Variable<CorrelationHandle>();

InitializeCorrelation OrderIdCorrelation = new InitializeCorrelation
{
    Correlation = OrderIdHandle,
    CorrelationData = { { "OrderId", new InArgument<string>(OrderId) } }
};

Receive StartOrder = new Receive
{
    CanCreateInstance = true,
    ServiceContractName = "IOrderService",
    OperationName = "StartOrder"
};

SendReply ReplyToStartOrder = new SendReply
{
    Request = StartOrder,
    Content = SendParametersContent.Create(new Dictionary<string, InArgument> { { "OrderId", new InArgument<string>((env) => OrderId.Get(env)) } }),
};

// Other messaging activities omitted...

L'attività InitializeCorrelation viene quindi utilizzata nel flusso di lavoro, dopo il popolamento delle variabili contenenti i dati ma prima dell'attività Receive correlata all'elemento CorrelationHandle inizializzato.

// Construct a workflow using OrderIdCorrelation, StartOrder, ReplyToStartOrder,
// and other messaging activities.
Activity wf = new Sequence
{
    Variables =
    {
        OrderId,
        Item,
        OrderIdHandle
    },
    Activities =
    {
        // Wait for a new order.
        StartOrder,
        // Assign a unique identifier to the order.
        new Assign<string>
        {
            To = new OutArgument<string>( (env) => OrderId.Get(env)),
            Value = new InArgument<string>( (env) => Guid.NewGuid().ToString() )
        },
        ReplyToStartOrder,
        // Initialize the correlation.
        OrderIdCorrelation,
        // Wait for an item to be added to the order.
        AddItem,
        ReplyToAddItem
     }
};

Configurazione di query XPath mediante Progettazione flussi di lavoro

Negli esempi precedenti le attività e le query XPath utilizzate nelle query del messaggio sono state specificate nel codice. Progettazione flussi di lavoro in Visual Studio 2010 fornisce inoltre la possibilità di generare query XPath dai tipi DataContract per la correlazione basata sul contenuto. La prima query XPath nell'esempio precedente è stata configurata per SendReply.

SendReply ReplyToStartOrder = new SendReply
{
    Request = StartOrder,
    Content = SendParametersContent.Create(new Dictionary<string, InArgument>
        { { "OrderId", new InArgument<string>((env) => OrderId.Get(env)) } }),
    CorrelationInitializers =
    {
        new QueryCorrelationInitializer
        {
            CorrelationHandle = OrderIdHandle,
            MessageQuerySet = new MessageQuerySet
            {
                {
                    "OrderId", 
                    new XPathMessageQuery("sm:body()/tempuri:StartOrderResponse/tempuri:OrderId")
                }
            }
        }
    }
};

Per configurare la query XPath per un'attività di messaggistica in Progettazione flussi di lavoro, selezionare l'attività all'interno dell'utilità. Se l'attività è in fase di inizializzazione della correlazione, come nell'esempio precedente, fare clic sul pulsante con i puntini di sospensione per la proprietà CorrelationInitializers nella finestra Proprietà. Viene visualizzata la finestra di dialogo Aggiungi inizializzatori di correlazione. Da questa finestra di dialogo è possibile specificare il tipo di correlazione e selezionare il contenuto utilizzato per la correlazione. La variabile CorrelationHandle viene specificata nella casella Aggiungi inizializzatore e il tipo di correlazione e dati utilizzati per la correlazione vengono selezionati nella sezione Query XPath della finestra di dialogo.

Finestra di dialogo degli inizializzatori di correlazione

La seconda query XPath nell'esempio precedente è stata configurata nell'attività Receive.

Receive AddItem = new Receive
{
    ServiceContractName = "IOrderService",
    OperationName = "AddItem",
    CorrelatesWith = OrderIdHandle,
    CorrelatesOn = new MessageQuerySet
    {
        {
            "OrderId", 
              new XPathMessageQuery("sm:body()/tempuri:AddItem/tempuri:OrderId")
        }
    },
    Content = ReceiveParametersContent.Create(new Dictionary<string, OutArgument>
        { { "OrderId", new OutArgument<string>(OrderId) },  
        { "Item", new OutArgument<string>(Item) } })
};

Per configurare la query XPath per un'attività di messaggistica che non inizializza la correlazione, selezionare l'attività in Progettazione flussi di lavoro, quindi fare clic sul pulsante con i puntini di sospensione per la proprietà CorrelatesOn nella finestra Proprietà. Viene visualizzata la finestra di dialogo Definizione di CorrelatesOn.

Definizione di CorrelatesOn

Da questa finestra di dialogo è possibile specificare CorrelationHandle e sceglie elementi nell'elenco Query XPath per compilare la query XPath.