Inhaltsbasiert
Dieses Thema gilt für Windows Workflow Foundation 4.
Wenn Workflowdienste mit Clients und anderen Diensten kommunizieren, sind in den ausgetauschten Nachrichten häufig Daten enthalten, die eine Nachricht eindeutig mit einer bestimmten Instanz verknüpfen. Die inhaltsbasierte Korrelation verwendet diese Daten in der Nachricht, z. B. eine Kundennummer oder Bestellt-ID, um Nachrichten an die richtige Workflowinstanz weiterzuleiten. In diesem Thema wird erklärt, wie Sie die inhaltsbasierte Korrelation in Workflows verwenden.
Verwenden der inhaltsbasierten Korrelation
Die inhaltsbasierte Korrelation wird verwendet, wenn ein Workflowdienst über mehrere Methoden verfügt, auf die von einem einzelnen Client zugegriffen wird, und ein Datenelement in den ausgetauschten Nachrichten die gewünschte Instanz angibt.
Hinweis: |
---|
Die inhaltsbasierte Korrelation ist nützlich, wenn die Kontextkorrelation nicht verwendet werden kann, weil es sich bei der Bindung nicht um eine der unterstützten Bindungen für den Kontextaustausch handelt. Weitere Informationen über zur Kontextkorrelation finden Sie unter Kontextaustausch. |
Jede bei dieser Kommunikation verwendete Messagingaktivität muss die Position der Daten in der Nachricht angeben, die die Instanz eindeutig identifizieren. Dazu wird MessageQuerySet mit QueryCorrelationInitializer oder CorrelatesOn bereitgestellt, um die Nachricht nach einem oder mehreren Datenelementen abzufragen, die die Instanz eindeutig identifizieren.
Vorsicht: |
---|
Die Daten zur Identifikation der Instanz werden per Hash in einen Korrelationsschlüssel umgewandelt. Dabei müssen Sie sicherstellen, dass die für die Korrelation verwendeten Daten eindeutig sind, da sonst Konflikte im Hashschlüssel auftreten und Nachrichten ggf. falsch weitergeleitet werden können. Wenn eine Korrelation z. B. ausschließlich auf einem Kundennamen basiert, kann es zu einem Konflikt kommen, da es möglicherweise mehrere Kunden mit dem gleichen Namen gibt. Der Doppelpunkt (:) darf nicht als Bestandteil der Daten verwendet werden, mit denen die Meldung korreliert wird, da hiermit bereits Schlüssel und Wert der Meldungsabfrage begrenzt werden, um die Zeichenfolge zu bilden, für die anschließend der Hashwert berechnet wird. |
Im folgenden Beispiel gibt der ursprüngliche Receive/SendReply in einem Workflowdienst eine OrderId
zurück, die dann auf den Aufruf der folgenden Receive-Aktivität im Workflowdienst hin vom Client zurück übergeben wird.
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.
Im vorherigen Beispiel wird eine von der SendReply-Antwort initialisierte inhaltsbasierte Korrelation veranschaulicht. Der MessageQuerySet gibt an, dass die Dateneinheit, mit der nachfolgende Nachrichten an diesen Dienst identifiziert werden, die OrderId
ist.
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")
}
}
}
}
};
Die Receive-Aktivität, die der SendReply im Workflow folgt, folgt der Korrelation, die von der SendReply initialisiert wurde. Beide Aktivitäten haben den gleichen CorrelationHandle, aber jede hat einen eigenen MessageQuerySet und eine eigene XPathMessageQuery, die angeben, wo in der jeweiligen Nachricht die identifizierenden Daten enthalten sind. Auf die die Korrelation initialisierende Aktivität hin wird dieser MessageQuerySet in der CorrelationInitializers-Eigenschaft angegeben, und bei weiteren Receive-Aktivitäten wird er mit der CorrelatesOn-Eigenschaft angegeben.
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) } })
};
Eine inhaltsbasierte Korrelation kann von jeder Messagingaktivität (Send, Receive, SendReply, ReceiveReply) initialisiert werden, wenn die Daten als Teil einer Nachricht weitergegeben werden. Wenn die entsprechenden Daten nicht als Teil einer Nachricht weitergegeben werden, können sie unter Verwendung der InitializeCorrelation-Aktivität ausdrücklich initialisiert werden. Wenn zur eindeutigen Identifizierung der Nachricht verschiedene Daten erforderlich sind, können dem MessageQuerySet mehrere Abfragen hinzugefügt werden. In diesen Beispielen wurde ein CorrelationHandle explizit für jede der Aktivitäten bereitgestellt, die die CorrelatesWith-Eigenschaft oder die CorrelationHandle-Eigenschaft verwenden, aber wenn nur eine Korrelation für den ganzen Workflow erforderlich ist, z. B. in diesem Beispiel, wo alles mit OrderId
korreliert, ist die von WorkflowServiceHost bereitgestellte implizite Korrelationshandleverwaltung ausreichend.
Verwenden der InitializeCorrelation-Aktivität
Im vorherigen Beispiel wurde die OrderId
durch die SendReply-Aktivität an den Aufrufer weitergegeben, und hier wurde die Korrelation initialisiert. Das gleiche Verhalten kann mit der InitializeCorrelation-Aktivität erreicht werden. Die InitializeCorrelation-Aktivität akzeptiert den CorrelationHandle und ein Wörterbuch von Elementen, die die Daten darstellen, mit denen die Nachricht der richtigen Instanz zugeordnet wird. Um im vorhergehenden Beispiel die InitializeCorrelation-Aktivität zu verwenden, entfernen Sie die CorrelationInitializers aus der SendReply-Aktivität, und initialisieren Sie die Korrelation mit der InitializeCorrelation-Aktivität.
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...
Die InitializeCorrelation-Aktivität wird dann im Workflow verwendet, nachdem die die Daten enthaltenden Variablen aufgefüllt wurden, aber vor der Receive-Aktivität, die dem initialisierten CorrelationHandle entspricht.
// 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
}
};
Konfigurieren von XPath-Abfragen mit Workflow-Designer
In den vorherigen Beispielen wurden die in der Nachricht verwendeten Aktivitäten und XPath-Abfragen im Code angegeben. Der Workflow-Designer in Visual Studio 2010 bietet auch die Möglichkeit, XPaths aus DataContract-Typen für inhaltsbasierte Korrelation zu generieren. Der erste im vorherigen Beispiel konfigurierte XPath wurde für die SendReply konfiguriert.
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")
}
}
}
}
};
Um den XPath für eine Messagingaktivität im Workflow-Designer zu konfigurieren, wählen Sie die Aktivität im Workflow-Designer aus. Wenn die Aktivität die Korrelation initialisiert, wie im vorherigen Beispiel, klicken Sie im Eigenschaftenfenster auf die Schaltfläche mit den Auslassungspunkten für die CorrelationInitializers-Eigenschaft. Hierdurch wird das Dialogfeld Korrelationsinitialisierer hinzufügen angezeigt. In diesem Dialogfeld können Sie die Korrelationsart angeben und den Inhalt auswählen, der für die Korrelation verwendet werden soll. Die CorrelationHandle-Variable wird im Feld Initialisierer hinzufügen angegeben. Der Typ und die Daten der Korrelation werden im Abschnitt XPath-Abfragen des Dialogfelds ausgewählt.
Die zweite XPath-Abfrage im vorherigen Beispiel wurde in der Receive-Aktivität konfiguriert.
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) } })
};
Um die XPath-Abfrage für eine Messagingaktivität zu konfigurieren, die nicht die Korrelation initialisiert, wählen Sie die Aktivität im Workflow-Designer aus, und klicken Sie dann im Eigenschaftenfenster auf die Schaltfläche mit den Auslassungspunkten für die CorrelatesOn-Eigenschaft. Hierdurch wird das Dialogfeld CorrelatesOn-Definition angezeigt.
In diesem Dialogfeld geben Sie den CorrelationHandle an und wählen Elemente in der Liste XPath-Abfragen aus, um die XPath-Abfrage zu erstellen.