Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este tema se enumeran los procedimientos recomendados para crear contratos de datos que pueden evolucionar fácilmente con el tiempo. Para obtener más información sobre los contratos de datos, consulte los temas de Uso de contratos de datos.
Nota sobre la validación de esquemas
En la descripción del control de versiones del contrato de datos, es importante tener en cuenta que el esquema de contrato de datos exportado por Windows Communication Foundation (WCF) no tiene compatibilidad con el control de versiones, excepto el hecho de que los elementos están marcados como opcionales de forma predeterminada.
Esto significa que incluso el escenario de control de versiones más común, como agregar un nuevo miembro de datos, no se puede implementar de una manera que sea perfecta con respecto a un esquema determinado. Las versiones más recientes de un contrato de datos (con un nuevo miembro de datos, por ejemplo) no se validan mediante el esquema anterior.
Sin embargo, hay muchos escenarios en los que no se requiere el cumplimiento estricto del esquema. Muchas plataformas de servicios web, incluidos WCF y servicios web XML creados con ASP.NET, no realizan la validación de esquemas de forma predeterminada y, por tanto, toleran elementos adicionales que no se describen en el esquema. Al trabajar con estas plataformas, muchos escenarios de control de versiones son más fáciles de implementar.
Por lo tanto, hay dos conjuntos de directrices de control de versiones del contrato de datos: un conjunto para escenarios en los que es importante la validez estricta del esquema y otro conjunto para escenarios cuando no lo es.
Control de versiones cuando se requiere la validación del esquema
Si se requiere una validez estricta del esquema en todas las direcciones (nuevos a antiguos y antiguos a nuevos), los contratos de datos deben considerarse inmutables. Si se requiere el control de versiones, se debe crear un nuevo contrato de datos, con un nombre o espacio de nombres diferente, y el contrato de servicio que use el tipo de datos se debe versionar en consecuencia.
Por ejemplo, un contrato de servicio de procesamiento de pedidos de compra denominado PoProcessing
con una PostPurchaseOrder
operación toma un parámetro que se ajusta a un PurchaseOrder
contrato de datos. Si el PurchaseOrder
contrato tiene que cambiar, debe crear un nuevo contrato de datos, es decir, PurchaseOrder2
, que incluye los cambios. A continuación, debe administrar la versión en el nivel del contrato de servicios. Por ejemplo, mediante la creación de una PostPurchaseOrder2
operación que toma el PurchaseOrder2
parámetro o mediante la creación de un PoProcessing2
contrato de servicio donde la PostPurchaseOrder
operación toma un PurchaseOrder2
contrato de datos.
Tenga en cuenta que los cambios en los contratos de datos a los que hacen referencia otros contratos de datos también se extienden a la capa del modelo de servicio. Por ejemplo, en el escenario anterior, el PurchaseOrder
contrato de datos no necesita cambiar. Sin embargo, contiene un miembro de datos de un contrato de datos Customer
, que a su vez contiene un miembro de datos del contrato de datos Address
, el cual sí necesita ser cambiado. En ese caso, tendría que crear un Address2
contrato de datos con los cambios necesarios, un Customer2
contrato de datos que contenga el Address2
miembro de datos y un PurchaseOrder2
contrato de datos que contenga un Customer2
miembro de datos. Como en el caso anterior, el contrato de servicio también tendría que ser versionado.
Aunque en estos ejemplos se cambian los nombres (anexando un "2"), la recomendación es cambiar los espacios de nombres en lugar de los nombres anexando nuevos espacios de nombres con un número de versión o una fecha. Por ejemplo, el contrato de datos http://schemas.contoso.com/2005/05/21/PurchaseOrder
cambiaría por el contrato de datos http://schemas.contoso.com/2005/10/14/PurchaseOrder
.
Para obtener más información, consulte Procedimientos recomendados: Control de versiones del servicio.
En ocasiones, debe garantizar el cumplimiento estricto del esquema para los mensajes enviados por la aplicación, pero no puede confiar en que los mensajes entrantes sean estrictamente compatibles con el esquema. En este caso, existe el peligro de que un mensaje entrante contenga datos extraños. WCF almacena y devuelve los valores extraños, lo que resulta en el envío de mensajes que no son válidos según el esquema. Para evitar este problema, la característica de ida y vuelta debe desactivarse. Esto se puede hacer de dos maneras.
No implemente la IExtensibleDataObject interfaz en ninguno de sus tipos.
Aplique el atributo ServiceBehaviorAttribute al contrato de servicio con la propiedad IgnoreExtensionDataObject establecida en
true
.
Para obtener más información, consulte Contratos de datos compatibles con el reenvío.
Control de versiones cuando no se requiere la validación de esquemas
El cumplimiento estricto del esquema rara vez es necesario. Muchas plataformas toleran elementos adicionales no descritos por un esquema. Mientras se tolere esto, se puede usar el conjunto completo de características descritas en Versionado de Contratos de Datos y Forward-Compatible Contratos de Datos. Se recomiendan las instrucciones siguientes.
Algunas de las instrucciones deben seguirse exactamente para enviar nuevas versiones de un tipo donde se espera uno anterior o enviar uno antiguo donde se espera el nuevo. Otras directrices no son estrictamente necesarias, pero se enumeran aquí porque pueden verse afectadas por el futuro del control de versiones de esquema.
No intente controlar las versiones de los contratos de datos por herencia de tipo. Para crear versiones posteriores, cambie el contrato de datos en un tipo existente o cree un nuevo tipo no relacionado.
Se permite el uso de herencia junto con contratos de datos, siempre que la herencia no se use como mecanismo de control de versiones y que se sigan ciertas reglas. Si un tipo se deriva de un tipo base determinado, no lo convierta en un tipo base diferente en una versión futura (a menos que tenga el mismo contrato de datos). Hay una excepción a esto: puede insertar un tipo en la jerarquía entre un tipo de contrato de datos y su tipo base, pero solo si no contiene miembros de datos con los mismos nombres que otros miembros en las versiones posibles de los otros tipos de la jerarquía. En general, el uso de miembros de datos con los mismos nombres en distintos niveles de la misma jerarquía de herencia puede provocar problemas graves de control de versiones y debe evitarse.
A partir de la primera versión de un contrato de datos, implemente siempre IExtensibleDataObject para habilitar la ida y vuelta. Para obtener más información, consulte Forward-Compatible Contratos de datos. Si ha publicado una o varias versiones de un tipo sin implementar esta interfaz, implempleela en la siguiente versión del tipo.
En versiones posteriores, no cambie el nombre del contrato de datos ni el espacio de nombres. Si cambia el nombre o el espacio de nombres del tipo subyacente al contrato de datos, asegúrese de conservar el nombre y el espacio de nombres del contrato de datos mediante los mecanismos adecuados, como la Name propiedad de DataContractAttribute. Para obtener más información sobre la nomenclatura, vea Nombres de contrato de datos.
En versiones posteriores, no cambie los nombres de ningún miembro de datos. Si cambia el nombre del campo, propiedad o evento que subyace al miembro de datos, use la propiedad
Name
de DataMemberAttribute para conservar el nombre existente del miembro de datos.En versiones posteriores, no cambie el tipo de ningún campo, propiedad o evento subyacente a un miembro de datos de forma que el contrato de datos resultante para ese miembro de datos cambie. Tenga en cuenta que los tipos de interfaz son equivalentes a Object para determinar el contrato de datos esperado.
En versiones posteriores, no cambie el orden de los miembros de datos existentes mediante el ajuste de la propiedad Order del atributo DataMemberAttribute.
En versiones posteriores, se pueden agregar nuevos miembros de datos. Siempre deben seguir estas reglas:
La IsRequired propiedad siempre debe dejarse en su valor predeterminado de
false
.Si el miembro no acepta el valor predeterminado
null
o cero, se debería proporcionar un método de devolución de llamada mediante OnDeserializingAttribute para proporcionar un valor predeterminado razonable en caso de que el miembro no se encuentre en la secuencia de entrada. Para obtener más información sobre la devolución de llamada, consulte Devoluciones de llamada de serialización tolerante a versiones.La DataMemberAttribute.Order propiedad debe usarse para asegurarse de que todos los miembros de datos recién agregados aparecen después de los miembros de datos existentes. La manera recomendada de hacerlo es la siguiente: Ninguno de los miembros de datos de la primera versión del contrato de datos debe tener su
Order
propiedad establecida. Todos los miembros de datos agregados en la versión 2 del contrato de datos deben tener suOrder
propiedad establecida en 2. Todos los miembros de datos agregados en la versión 3 del contrato de datos deben tener suOrder
establecido en 3, etc. Se permite tener más de un miembro de datos establecido en el mismo número deOrder
.
No elimine miembros de datos en versiones posteriores, incluso si la IsRequired propiedad se dejó en su valor predeterminado de
false
en versiones anteriores.No cambie la propiedad
IsRequired
en ningún miembro de datos existente de una versión a otra.Para los miembros de datos necesarios (donde
IsRequired
estrue
), no cambie la propiedadEmitDefaultValue
entre versiones.No intente crear jerarquías de control de versiones bifurcadas. Es decir, siempre debe haber una ruta de acceso en al menos una dirección de cualquier versión a cualquier otra versión con solo los cambios permitidos por estas directrices.
Por ejemplo, si la versión 1 de un contrato de datos de Persona contiene solo el miembro de datos llamado Nombre, no debe crear la versión 2a del contrato agregando solo el miembro llamado Edad y la versión 2b agregando solo el miembro llamado Dirección. Pasar de 2a a 2b implicaría quitar la edad y agregar la dirección; ir en la otra dirección implicaría quitar la dirección y agregar la edad. Estas directrices no permiten quitar miembros.
Por lo general, no debe crear nuevos subtipos de tipos de contrato de datos existentes en una nueva versión de la aplicación. Del mismo modo, no debe crear nuevos contratos de datos que se usen en lugar de miembros de datos declarados como "Object" o como tipos de interfaz. La creación de estas clases nuevas solo se permite cuando sabe que puede agregar los nuevos tipos a la lista de tipos conocidos de todas las instancias de la aplicación anterior. Por ejemplo, en la versión 1 de su aplicación, puede tener el tipo de contrato de datos LibraryItem con Book y subtipos de contrato de datos Newspaper. LibraryItem tendría entonces una lista de tipos conocidos que contiene Book y Newspaper. Suponga que ahora agrega un tipo Magazine en la versión 2 qué es un subtipo de LibraryItem. Si envía una instancia de Magazine de la versión 2 a la versión 1, el contrato de datos de Magazine no se encuentra en la lista de tipos conocidos y se produce una excepción.
No debe agregar ni quitar miembros de enumeración entre diferentes versiones. No debería tampoco cambiar el nombre de los miembros de enumeración, a menos que use la propiedad Name del atributo
EnumMemberAttribute
para mantener iguales sus nombres en el modelo de contrato de datos.Las colecciones son intercambiables en el modelo de contrato de datos, tal como se describe en Tipos de recopilación en contratos de datos. Esto permite un gran grado de flexibilidad. Sin embargo, asegúrese de que no cambie accidentalmente un tipo de colección de forma no intercambiable de la versión a la versión. Por ejemplo, no cambie de una colección no personalizada (es decir, sin el
CollectionDataContractAttribute
atributo) a una colección personalizada o a una colección personalizada a una no personalizada. Además, no cambie las propiedades en elCollectionDataContractAttribute
de una versión a otra. El único cambio permitido es agregar una propiedad Name o Namespace si el nombre o el espacio de nombres del tipo de colección subyacente ha cambiado y debe hacer que su nombre de contrato de datos y el espacio de nombres sean los mismos que en una versión anterior.
Algunas de las directrices enumeradas aquí se pueden omitir de forma segura cuando se aplican circunstancias especiales. Asegúrese de comprender completamente los mecanismos de serialización, deserialización y esquema implicados antes de desviarse de las instrucciones.
Consulte también
- Name
- DataContractAttribute
- Order
- IsRequired
- IExtensibleDataObject
- ServiceBehaviorAttribute
- ExtensionData
- ExtensionDataObject
- OnDeserializingAttribute
- Uso de contratos de datos
- Control de versiones del contrato de datos
- Nombres de contrato de datos
- Forward-Compatible Contratos de Datos
- Devoluciones de llamadas en la serialización tolerante a versiones