文件永久性提供程序示例

本示例演示如何创建使用持久性服务的永久性提供程序。服务实例的状态存储在计算机上的文件中。

该示例还包含一个计算器服务实现,它与持久性服务相同。区别在于此服务使用在示例中创建的文件永久性提供程序,而不使用标准的锁定 SQL 永久性提供程序。

提示

此示例需要安装 .NET Framework 3.5 版才能生成和运行。若要打开项目和解决方案文件,需要使用 Visual Studio 2008。

计算器客户端示例必须与此服务一起运行(有关更多信息,请参见 本主题最后的安装过程)。

文件永久性提供程序

本示例中的文件永久性提供程序在文件 FilePersistenceProviderFactory.cs 中定义。请注意,实际的 FilePersistenceProvider 类位于嵌入的类中。为了创建文件永久性提供程序,使用了工厂模式,在这种模式中,工厂会在需要时将实际的永久性提供程序类传递给服务运行时。这是在 WCF 中创建提供程序的标准方式。

文件永久性提供程序工厂类继承自 PersistenceProviderFactory 抽象类。PersistenceProviderFactory 抽象类在下面的代码中定义。

namespace System.ServiceModel.Persistence
{
    public abstract class PersistenceProviderFactory : CommunicationObject
    {
        protected PersistenceProviderFactory();

        public abstract PersistenceProvider CreateProvider(Guid id);
    }
}

请注意,PersistenceProviderFactory 继承自 CommunicationObject 抽象类。CommunicationObject 提供了在服务运行时对象的整个使用期内管理对象生存期所需要的方法。

提供程序的工厂模式有助于确保工厂能管理跨提供程序所有实例的所有公共资源。例如,在文件永久性提供程序的情况下,工厂可以确定存储永久性文件并随后跨实际文件永久性提供程序的所有实例来共享永久性文件的位置。

因此,服务的每个实例都会有一个提供程序的实例。每个主机也都有一个工厂的实例。

文件永久性提供程序本身继承自 PersistenceProvider 抽象类。此类在下面的代码中定义。

namespace System.ServiceModel.Persistence
{
    public abstract class PersistenceProvider : CommunicationObject
    {
        protected PersistenceProvider(Guid id);

        public Guid Id { get; }

        public abstract IAsyncResult BeginCreate(object instance, TimeSpan timeout, AsyncCallback callback, object state);
        public abstract IAsyncResult BeginDelete(object instance, TimeSpan timeout, AsyncCallback callback, object state);
        public abstract IAsyncResult BeginLoad(TimeSpan timeout, AsyncCallback callback, object state);
        public virtual IAsyncResult BeginLoadIfChanged(TimeSpan timeout, object instanceToken, AsyncCallback callback, object state);
        public abstract IAsyncResult BeginUpdate(object instance, TimeSpan timeout, AsyncCallback callback, object state);
        public abstract object Create(object instance, TimeSpan timeout);
        public abstract void Delete(object instance, TimeSpan timeout);
        public abstract object EndCreate(IAsyncResult result);
        public abstract void EndDelete(IAsyncResult result);
        public abstract object EndLoad(IAsyncResult result);
        public virtual bool EndLoadIfChanged(IAsyncResult result, out object instance);
        public abstract object EndUpdate(IAsyncResult result);
        public abstract object Load(TimeSpan timeout);
        public virtual bool LoadIfChanged(TimeSpan timeout, object instanceToken, out object instance);
        public abstract object Update(object instance, TimeSpan timeout);    
    }
}

永久性提供程序类也是一个通信对象。永久性提供程序中有 4 个方法:Create()Update()Load()Delete()。定义了这些方法的异步变体以及这些异步变体的重载。下面的规则适用于在文件中存储实例的状态:

  • 实际文件存储在承载服务的计算机的 Temp 目录中一个名为 FilePersistenceProvider 的目录中。
  • 实例的状态存储在一个文件中,该文件的名称是该实例的唯一标识符。此文件使用 .bin 扩展名进行存储。
  • 在必须删除某个文件时,实际上并未删除该文件,而是将其重命名为“deleted”。

永久性提供程序的配置

在使用之前,必须在服务的配置文件中指定文件永久性提供程序。永久性提供程序的配置是在配置文件的 servicebBehaviors 节中指定的。本示例演示 Web.config 文件中的条目。

<behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior"  >
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceCredentials>
            <windowsAuthentication allowAnonymousLogons="false" includeWindowsGroups="true" />
          </serviceCredentials>
          <persistenceProvider type="Microsoft.WorkflowServices.Samples.FilePersistenceProviderFactory, DurableServiceFactory, Version=1.0.0.0"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>  

持久性服务代码 – 服务协定

下面的代码演示计算器服务的服务协定。

[ServiceContract(Namespace = "http://Microsoft.WorkflowServices.Samples")]
    public interface ICalculator
    {
        [OperationContract()]
        int PowerOn();
        [OperationContract()]
        int Add(int value);
        [OperationContract()]
        int Subtract(int value);
        [OperationContract()]
        int Multiply(int value);
        [OperationContract()]
        int Divide(int value);
        [OperationContract()]
        void PowerOff();
    }  

服务实现

在下面的代码中,服务实现中使用 DurableServiceAttribute 属性来指定该服务是持久性服务。

[Serializable]
[DurableService]
public class DurableCalculator : ICalculator
{
    int currentValue = default(int);

    [DurableOperation(CanCreateInstance=true)]
    public int PowerOn()
    {
        return currentValue;
    }

    [DurableOperation()]
    public int Add(int value)
    {
        return (currentValue += value);
    }

    [DurableOperation()]
    public int Subtract(int value)
    {
        return (currentValue -= value);
    }

    [DurableOperation()]
    public int Multiply(int value)
    {
        return (currentValue *= value);
    }

    [DurableOperation()]
    public int Divide(int value)
    {
        return (currentValue /= value);
    }

    [DurableOperation(CompletesInstance=true)]
    public void PowerOff()
    {
    }

}

DurableOperationAttribute 属性指定在操作完成后保存实例状态。

有 2 个参数可以在 DurableOperationAttribute 属性中使用。CanCreateInstance 属性指定在调用操作时创建实例。CompletesInstance 属性指定一旦在其上指定此属性的操作运行结束,服务实例即完成。操作完成后,状态也即从数据库中删除。

下面的代码演示在 Internet 信息服务 (IIS) 中承载此示例的 .svc 文件。

<%@ServiceHost language=c# Debug="true" Service="Microsoft.WorkflowServices.Samples.DurableCalculator" Factory="System.ServiceModel.Activation.ServiceHostFactory" %>

服务的绑定是在 Web.config 文件中配置的。WSHttpContextBinding 绑定帮助维护用于将请求路由给特定应用程序实例的上下文。指定永久性提供程序的永久性提供程序条目位于 ServiceBehaviors 节。

设置、生成和运行示例

  1. 确保按照 Windows Communication Foundation 示例的一次性安装过程中的安装说明进行操作。

  2. 在 IIS 中,对 ServiceModelSamples 虚拟目录启用 Windows 身份验证。

    在 IIS 5.1 或 6.0 中启用 Windows 身份验证:

    1. 打开一个命令提示符窗口,并键入**“start inetmgr”** 以打开 Internet 信息服务 (IIS) MMC 管理单元。
    2. 右击**“默认网站”内的虚拟根目录“ServiceModelSamples”,单击“属性”,然后单击“目录安全性”**选项卡。
    3. 在**“身份验证和访问控制”之下,单击“编辑”**。
    4. 在**“身份验证方法”对话框中,选择“集成 Windows 身份验证”**。

    在 IIS 7.0 中启用 Windows 身份验证:

    1. 打开一个命令提示符窗口,并键入**“start inetmgr”** 以打开 Internet 信息服务 (IIS) MMC 管理单元。
    2. 选择**“默认网站”内的“ServiceModelSamples”**虚拟根目录。
    3. 在**“ServiceModelSamples”主窗格内,双击“IIS”组内的“身份验证”**。
    4. 选择**“Windows 身份验证”并选择“启用”**操作。
  3. 生成项目。此项目将生成并更新 ServiceModelSamples。

  4. 若要确保正确安装了服务,请指向地址 https://localhost/servicemodelsamples/service.svc。您应当会看到服务的帮助页。若要查看 Web 服务描述语言 (WSDL),请键入 https://localhost/servicemodelsamples/service.svc?wsdl。

  5. 若要运行此示例,必须使用计算器客户端示例。这是一个使用 Windows Presentation Foundation (WPF)(可作为服务的客户端)创建的计算器用户界面。若要测试服务的持久性本质,请在计算器服务正在运行时关闭客户端并重新打开客户端。计算器客户端会重新与同一个服务实例进行通信,并在底部显示实例 ID。在进行第一次调用时,计算器客户端使用名为 Client.ctx 的文本文件将上下文存储在一个持久位置(在本例中,存储在示例的 \bin 目录中)。重新打开客户端时,此客户端将检查文件是否存在。如果文件存在,则客户端会将存储的上下文应用于要创建的通道。如果服务已经完成并且您打开了此客户端,而 Client.ctx 文件仍在您的 \bin 目录中,则它将尝试向通道应用上下文。您将收到错误,因为不存在要与其进行通信的服务。请删除文件并重试。

  6. 还可以通过重新启动 IIS 回收服务。因为在每次操作之后都要使用持久性存储区,所以服务的状态为“已存储”。因此,当您尝试在重新启动 IIS 后从客户端与该服务进行通信时,服务基础结构将从持久性存储区收到实例,而您可以与同一个实例进行通信。

    提示

    在重新启动 IIS 之后首次调用一个操作时,您将收到 MessageSecurityException 异常,这是由通道上过期的安全令牌引起的。如果调用另一项操作,则此操作将会成功。

Send comments about this topic to Microsoft.
© 2007 Microsoft Corporation. All rights reserved.