在 WF4 中建立多个 RECEIVE 之间的关联
一个简单的程序来理解 WF4 中的关联。
引言
我的目标是通过一个简单的应用程序介绍 WF4 中固有的关联(Correlation)功能。您需要安装 VS 2010 B2 才能探索附带的代码。我在这里讨论的关联是 WF 服务多个接收(receives)之间的关联。在早期版本中,我们必须使用 GUID 来显式建立关联。
创建关联应用程序的步骤
创建关联 WF4 应用程序涉及以下步骤。
- 创建数据实体库。
- 创建 WF 服务。
- 创建客户端应用程序来调用/使用 WF 服务。
场景
我选择的场景非常简单,以便于理解关联逻辑。在 WF4 中,您可以使用任何数据成员(用于唯一标识实例)来创建关联。我们以一个客户注册应用程序为例,该应用程序首先知道客户的名字,然后稍后更新姓氏。所以,显然,我们需要两个(2)个接收活动。
步骤 1:创建数据实体库
让我们开始创建 WF 服务和客户端之间共享的数据实体库。这个实体库将有 3 个 private
成员和 3 个 public
属性来访问和赋值。
- 启动 VS 2010 B2。
- 文件 -> 打开 -> 新建项目 -> 选择 VC# -> 类库,并将其命名为 Customer。
- 将 Class1.cs 重命名为 Customer.cs,并添加对
System.Runtime.Serialization
类的引用。 - 在代码中,使用“
using
”语句引用该类。在类声明的顶部添加[DataContract]
属性。添加三个private
成员以及用于名字、客户 ID 和姓氏的Public get
,set
属性。在每个属性的顶部添加 [DataMember
] 属性。
您的代码应如下所示...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
namespace Customer
{
[DataContract]
public class Customer
{
private string _firstName;
private string _lastName;
private Int32 _customerID;
[DataMember]
public string FirstName { get { return this._firstName; }
set { _firstName = value; } }
[DataMember]
public string LastName { get { return this._lastName; }
set { _lastName = value; } }
[DataMember]
public Int32 CustomerID { get { return this._customerID; }
set { _customerID = value; } }
}
}
步骤 2:创建 WF 服务
- 右键单击同一解决方案,然后添加一个类型为工作流控制台应用程序的新项目。双击 Workflow1.xaml 进入设计视图。从“Control Flow”拖放“Sequence”到设计窗口的中央。从 Messaging 工具栏部分拖放“ReceiveAndSendReply”到“Sequence”控件的正文上。再次从 Messaging 工具栏拖放同一个
ReceiveAndSendReply
到前面的ReceiveAndSendReply
下方。请参考图片查看 WF 设计(目前,请忽略图片中已更新的操作名称、文本等)。
- 单击外部 Sequence 控件。选择左下角的“Variables”,并创建以下变量。在此之前,通过单击解决方案资源管理器中的“添加引用”来引用此控制台应用程序的 Customer(实体库)。
变量名 变量类型 范围 __handle
关联句柄 序列 CurrCustomer
客户 序列 从下拉列表中,为
__handle
选择System.ServiceModel.Activities.CorrelationHandle
作为变量类型,同样,为CurrCustomer
变量选择Customer.Customer
。__handle
变量用作句柄,用于将下一个调用路由到已存在的实例,而CurrCustomer
将保存传递到服务的Customer
对象的当前状态。 - 选择主序列内的第一个 Sequence 控件中的“Receive”活动。在“Receive”活动的属性窗口中执行以下操作。
OperationName = CreateCustomer ServiceContractName = CustomerService CanCreateInstance = True (Check the check box) CorrelatesWith = __handle CorrelatesOn = From the Xpath Query Dropdown, select Customer ID
- 单击“Receive”框内的“View Parameters”按钮,为该活动从客户端应用程序添加参数。选择“Parameters”单选按钮并输入以下内容
名称 类型 AssignTo value
客户
CurrCustomer
此步骤将
Customer
对象分配给本地变量CurrCustomer
,以便在工作流服务中进一步处理。 - 在 Receive 和“
SendReplyToReceive
”控件之间添加“Assign”控件(来自工具栏的 Primitives 部分)。此操作用于在服务中分配任何值。在设计面板中选择此控件后,单击属性窗口中“To”旁边的按钮。您应该能够输入CurrCustomer.CustomerID
而没有任何错误。如果出现任何错误,会在框的末尾显示一个红色信息图像。单击“确定”并关闭。单击属性框中Value
旁边的按钮,并输入New Random().Next()
。这将为服务中现有的 Customer 对象分配一个新的Customer ID (integer)
)。单击“SendReplyToReceive”框的“View Parameters”按钮并添加以下内容名称 类型 值 resultAdd
字符串
"Customer Added. ID for " + CurrCustomer.FirstName is " + CurrCustomer.CustomerID.ToString()
注意:XAML 中要遵循的语法是 VB 语法。因此,我们应该同时学习 C# 和 VB。这个
resultAdd
将作为string
返回给客户端应用程序。 - 将 WriteLine 组件从 Primitives 部分拖放到
SendReplyToReceive
的旁边。这将在服务控制台窗口中打印信息,以便查看服务中发生了什么。 - 单击属性窗口中“Text”属性旁边的按钮,然后复制并粘贴以下内容
"Customer ID Created for " + CurrCustomer.FirstName + " " + CurrCustomer.LastName + "=" + CurrCustomer.CustomerID.ToString()
通过以上步骤,创建已传入 Customer 的 **Customer ID** 的一部分操作已完成。现在,我们将创建另一个 **Receive** 活动来为服务中已存在的 Customer 对象添加姓氏。
- 选择设计窗口中的第二个 Sequence,然后单击左下角的 Variables,并添加以下变量
名称 变量类型 范围 lName
字符串
序列 custID
Int32
序列 - 选择 Receive 活动,并向相应属性添加以下值
OperationName = AddLastName
ServiceContractName = CustomerService
CorrelatesWith = __handle
(这是关联第一个接收和第二个接收活动的部分)CorrelatesOn = 从 Xpath 查询下拉列表中选择“ID : Int32”。
这是我们将在客户端应用程序中传递的参数,如上一步所示。- 在设计区域的 Receive 和
SendReplyToReceive
部分之间插入 Primitives 部分的 Assign 组件。在 To 文本框中,输入CurrCustomer.LastName
。在 value 文本框中,输入lName
(本地变量名) - 单击
SendReplyToReceive
框中的“View Parameters”按钮,并添加以下内容。选择 parameters 选项按钮。名称 类型 值 resultAdd
字符串
"last Name " + CurrCustomer.LastName + " added to Customer ID " + CurrCustomer.CustomerID.ToString()
这是将返回给客户端应用程序的值。
- 最后,将
WriteLine
组件拖放到设计区域,并在 Text 属性中输入以下内容,以查看服务中发生了什么。"Customer Name :" + CurrCustomer.FirstName + " " + CurrCustomer.LastName + " ID : " + CurrCustomer.CustomerID.ToString()
我们完成了 XAML 中 WF4 服务的创建。
- 打开 WF Service App 的 Program.cs 文件,并输入以下内容。
- 引用
System.ServiceModel.Activities
和System.ServiceModel.Description
程序集。 - 在 main 方法中,复制并粘贴以下内容
string baseAddress="https://:8081/CustomerService"; using (WorkflowServiceHost shost = new WorkflowServiceHost(new Activity1(), new Uri(baseAddress))) { shost.Description.Behaviors.Add(new ServiceMetadataBehavior() {HttpGetEnabled = true }); shost.Open(); Console.WriteLine("CustomerService is listening @ " + baseAddress); Console.ReadLine(); }
变量 lName
用于保存从客户端应用程序传入的姓氏值,custID
则用于保存客户 ID。单击 receive 组件的“View Parameters”按钮,并添加以下变量。选择 Parameters 选项按钮。
名称 | 类型 | AssignTo |
value |
字符串 |
lName |
ID |
Int32 |
custID |
此时,我们不应该勾选 CanCreateInstance
属性,因为实例已经由第一个 Receive 创建,而从现在开始,我们将更新服务应用程序中已存在的 Customer
对象。
生成解决方案,并确保没有类型错误或任何其他编译错误。转到 WF Service Console App 的 bin/debug 文件夹并运行该控制台应用程序。
步骤 3:创建客户端应用程序调用 WF 服务
- 右键单击解决方案,添加 VC# 控制台应用程序,并将其命名为
ClientApp
。将Customer
库引用添加到项目中。右键单击ClientApp
的“Service Reference”,然后单击“Add Service reference”。在 Address 栏中键入 https://:8081/CustomerService,然后单击 Go。在 Services 框中,选择服务,然后单击 OK。现在,您已将引用添加到本地运行的服务中。注意:每次更改服务后,都需要更新客户端应用程序。
- 打开
ClientApp
的 Program.cs 文件,并将以下内容复制并粘贴到Main
方法中。ServiceReference1.CustomerServiceClient csClient = new CustomerServiceClient(); Customer.Customer cust = new Customer.Customer(); string fName; Console.WriteLine("Enter First Name : "); fName =Console.ReadLine(); cust.FirstName = fName; string response = csClient.CreateCustomer(cust); Console.WriteLine(response); Console.ReadLine(); try { Console.WriteLine("Enter last Name : "); cust.LastName = Console.ReadLine(); string response1 = csClient.AddLastName (cust.LastName.ToString(), cust.CustomerID); Console.WriteLine(response1); Console.ReadLine(); } catch (Exception ex) { //Publish the error }
好了。您已完成编码。现在,将 ClientApp
设置为启动项目,然后单击 Run 按钮。或者,您可以转到 ClientApp
的 bin/debug 文件夹并执行 EXE。
历史
- 2010年1月22日:初始发布