Cómo: Habilitar la persistencia para un servicio duradero

Los servicios duraderos son servicios Windows Communication Foundation (WCF) diseñados para ser duraderos y de ejecución prolongada, y para superar los reinicios de la aplicación y el servidor. Los servicios duraderos se conservan utilizando el proveedor predefinido, creado por un SqlPersistenceProviderFactory, o un proveedor de persistencia personalizado derivado del PersistenceProvider o del LockingPersistenceProvider de la clase abstracta.

La clase abstracta LockingPersistenceProvider deriva de PersistenceProvider y expone la funcionalidad para bloquear, desbloquear, cargar, guardar y eliminar información de estado del servicio de manera explícita. La información de estado del servicio se bloquea antes de que se realicen las operaciones de guardado o eliminación, de modo que no se produzcan contenciones de datos entre distintos hosts. Antes de que poder adquirir un bloqueo en los datos de estado, deben cumplirse los dos criterios siguientes:

  • El lockOwner del registro debe ser “null”.

  • El valor lockExpiration del registro debe ser menor que el DateTime actual (es decir, cualquier bloqueo anterior debe haber expirado).

Cuando se adquiere el bloqueo, el campo lockOwner del registro se establece en el id. de host del host de bloqueo (este valor será único para cada instancia del proveedor y se generará en el constructor del proveedor), y el valor lockExpiration del registro se establece en DateTime.UtcNow más el valor de tiempo de espera del bloqueo. (Éste es el valor proporcionado al constructor del proveedor de persistencia, o un valor predeterminado definido en la clase de implementación del proveedor. En la implementación SqlPersistenceProviderFactory predefinida, el valor predeterminado es cero, lo que significa que no se utiliza el bloqueo de forma predeterminada). Si el bloqueo ya está incluido, el valor de tiempo de espera del bloqueo también se actualizará si se llama a Lock o Load, con el conjunto de parámetros lockInstance establecido en True. El tiempo de espera del bloqueo también se actualizará si el bloqueo ya está incluido y se llama a Save con el parámetro unlockInstance establecido en False.

El SqlPersistenceProviderFactory crea una implementación predefinida de la clase abstracta LockingPersistenceProvider. SqlPersistenceProviderFactory utiliza SQL 2005 como almacén de persistencia y puede conservar información de estado en formato de texto o binario.

El SqlPersistenceProviderFactory puede crearse con hasta tres parámetros de constructor. La siguiente tabla muestra los tres parámetros del constructor:

lockTimeout

Tiempo de espera de la propiedad del bloqueo. La instancia de estado del servicio se desbloquea automáticamente finalizado este tiempo de espera. Un tiempo de espera de cero (el valor predeterminado) hará que no se utilice el bloqueo, y un valor de TimeSpan.MaxValue hará que los bloqueos nunca expiren.

connectionString

Cadena que contiene los parámetros utilizados para conectar con la base de datos SQL. Tenga en cuenta que al configurar el proveedor de persistencia mediante un archivo de configuración, la cadena de conexión se coloca en el nodo connectionStrings, en lugar de junto a otros parámetros de creación.

serializeAsText

Valor booleano que indica si la información de estado se conservará en formato XML o binario. El valor predeterminado es False (lo que indica una serialización binaria).

Los datos de estado del servicio se conservan en la tabla InstanceData. A continuación se muestran los campos de la tabla InstanceData.

id

Identificador único de la instancia de estado.

instanceType

Tipo de instancia que se está almacenando.

instance

Estado de instancia conservado como datos binarios. Será nulo si la instancia se conserva como texto.

instanceXml

Estado de instancia conservado como XML. Será nulo si la instancia se conserva como datos binarios.

created

Hora UTC a la que la instancia se escribió por primera vez en la base de datos.

lastUpdated

Hora UTC a la que la instancia se escribió por última vez en la base de datos.

lockOwner

El id. de host del host que posee actualmente el bloqueo en el registro, o “null” si ningún bloqueo está activo.

lockExpiration

Hora UTC a la que expirará el bloqueo.

El SqlPersistenceProviderFactory puede configurarse en código utilizando el constructor de clases, pero, normalmente, es preferible configurarlo (así como los proveedores de servicios en general) utilizando un archivo de configuración de aplicación. A continuación se muestra una configuración de ejemplo. (Tenga en cuenta que el formato de los archivos de configuración de servicio duraderos es el mismo que el de los servicios Windows Communication Foundation (WCF).)

<configuration>
  <connectionStrings>
    <add name="LocalConnection" 
      connectionString="
        Initial Catalog=SqlPersistence;
        Data Source=localhost;
        Integrated Security=SSPI;" 
    />
  </connectionStrings>  <system.serviceModel>
    <services>
      <service 
        name="SampleService"
        behaviorConfiguration="ServiceBehavior">
        <endpoint
          address="ISampleService_Basic"
          binding="basicHttpContextBinding"
          contract="SampleApplication.ISampleService"
        />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <persistenceProvider
            persistenceOperationTimeout="00:00:15"
            type="
              System.ServiceModel.Persistence.SqlPersistenceProviderFactory,
              System.WorkflowServices,
              Version=3.5.0.0",
              Culture=neutral,
              PublicKeyToken=31bf3856ad364e5"
            connectionStringName="LocalConnection",
            lockTimeout="00:10:00" 
          />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

Configuración de servicios duraderos

Servicio WCF implementado en el código conservado en un medio de almacenamiento, normalmente, una base de datos SQL. El servicio puede volver a cargarse de modo que un cliente se conecte con un servicio concreto en cualquier momento.

Un servicio duradero utiliza el mismo modelo de objetos que un servicio de flujo de trabajo, y el mismo mecanismo de canal de protocolo de contexto subyacente, de modo que los mensajes pueden enrutarse a la instancia correcta de un servicio.

La diferencia entre un servicio duradero escrito en código y otro escrito como flujo de trabajo, es que éste último puede conservarse en medio de una invocación de operación, mientras que un servicio duradero se conserva una vez completada la invocación de operación.

Para marcar una implementación de servicio como duradera, marque el servicio utilizando el DurableServiceAttribute. La siguiente tabla muestra el parámetro disponible para este atributo.

SaveStateInOperationTransaction

Establece, de manera explícita, todos los estados de instancia en transaccionales. Este marcador comprueba que ConcurrencyMode es Single, y que todas las operaciones se ejecutarán bajo una transacción. (TransactionScopeRequired debe establecerse en True, o debe establecerse TransactionFlowOption.)

Cuando el atributo está presente en un servicio, el método ApplyDispatchBehavior configurará los componentes DispatchRuntime necesarios para extraer correctamente un id. de instancia de un mensaje, enrutarlo a la instancia correcta, y realizar las operaciones de persistencia en torno a la invocación.

Las operaciones en servicios duraderos deberían marcarse con DurableOperationAttribute. La siguiente tabla muestra la propiedad para este atributo.

CompletesInstance

Especifica que la instancia se completará (y se conservará y descargará desde la memoria) una vez finalizada esta operación. El valor predeterminado es False.

El ejemplo de código siguiente muestra cómo crear un servicio duradero.

[ServiceContract()]
public interface IService1
{
    [OperationContract]
    string MyOperation1(string myValue);
    [OperationContract]
    string MyOperation2(DataContract1 dataContractValue);
}
[DurableService(MyPersistenceProvider)]
public class service1 : IService1
{
    [DurableOperation]
    public string MyOperation1(string myValue)
    {
        Return "Hello: " + myValue;
    }
    [DurableOperation]
    string MyOperation2(DataContract1 dataContractValue)
    {
        return "Hello: " + dataContractValue.DataName;
    }
}
[DataContract]
public class DataContract1
{
    string dataNameValue;
    [DataMember]
    public string DataName
    {
        get { return dataNameValue; }
        set { dataNameValue = value; }
    }
}

Consulte también

Otros recursos

Tutorial: Creación de un servicio duradero
Creación de servicios de flujo de trabajo y de servicios duraderos

Footer image

Copyright © 2007 Microsoft Corporation. Reservados todos los derechos.