Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este tópico lista as práticas recomendadas para criar contratos de dados que podem evoluir facilmente ao longo do tempo. Para obter mais informações sobre contratos de dados, consulte os tópicos sobre como usar contratos de dados.
Observação sobre validação de esquema
Ao discutir o controle de versão do contrato de dados, é importante observar que o esquema de contrato de dados exportado pelo WCF (Windows Communication Foundation) não tem suporte para controle de versão, exceto o fato de que os elementos são marcados como opcionais por padrão.
Isso significa que mesmo o cenário de versionamento mais comum, como a adição de um novo membro de dados, não pode ser implementado de forma transparente em relação a um determinado esquema. As versões mais recentes de um contrato de dados (com um novo membro de dados, por exemplo) não são validadas usando o esquema antigo.
No entanto, há muitos cenários em que a conformidade estrita do esquema não é necessária. Muitas plataformas de serviços Web, incluindo serviços Web WCF e XML criados usando ASP.NET, não executam a validação de esquema por padrão e, portanto, toleram elementos extras que não são descritos pelo esquema. Ao trabalhar com essas plataformas, muitos cenários de controle de versão são mais fáceis de implementar.
Portanto, há dois conjuntos de diretrizes de controle de versão do contrato de dados: um conjunto para cenários em que a validade estrita do esquema é importante e outro definido para cenários quando não é.
Controle de versão quando a validação de esquema é necessária
Se a validade estrita do esquema for necessária em todas as direções (novas para antigas e antigas para novas), os contratos de dados deverão ser considerados imutáveis. Se o controle de versão for necessário, um novo contrato de dados deverá ser criado, com um nome ou namespace diferente, e o contrato de serviço que usa o tipo de dados deverá ser atualizado adequadamente.
Por exemplo, um contrato de serviço de processamento de pedidos de compra denominado PoProcessing com uma operação PostPurchaseOrder recebe um parâmetro que está em conformidade com um contrato de dados PurchaseOrder. Se o PurchaseOrder contrato precisar ser alterado, você deverá criar um novo contrato de dados, ou seja, PurchaseOrder2que inclua as alterações. Em seguida, você deve lidar com o controle de versão no nível do contrato de serviço. Por exemplo, criando uma PostPurchaseOrder2 operação que usa o PurchaseOrder2 parâmetro ou criando um PoProcessing2 contrato de serviço em que a PostPurchaseOrder operação usa um PurchaseOrder2 contrato de dados.
Observe que as alterações nos contratos de dados referenciadas por outros contratos de dados também se estendem à camada do modelo de serviço. Por exemplo, no cenário anterior, o PurchaseOrder contrato de dados não precisa ser alterado. No entanto, ele contém um membro de dados de um contrato de dados Customer, que, por sua vez, continha um membro de dados do contrato de dados Address, que precisa ser alterado. Nesse caso, você precisaria criar um Address2 contrato de dados com as alterações necessárias, um Customer2 contrato de dados que contenha o membro de Address2 dados e um PurchaseOrder2 contrato de dados que contenha um Customer2 membro de dados. Como no caso anterior, o contrato de serviço também teria que ser versionado.
Embora nestes exemplos os nomes sejam alterados (acrescentando um "2"), a recomendação é alterar namespaces em vez de nomes acrescentando novos namespaces com um número de versão ou uma data. Por exemplo, o http://schemas.contoso.com/2005/05/21/PurchaseOrder contrato de dados seria alterado para o http://schemas.contoso.com/2005/10/14/PurchaseOrder contrato de dados.
Para obter mais informações, consulte As práticas recomendadas: controle de versão do serviço.
Ocasionalmente, você deve garantir a conformidade estrita do esquema para mensagens enviadas pelo seu aplicativo, mas não pode contar com as mensagens de entrada para estar estritamente em conformidade com o esquema. Nesse caso, há o perigo de que uma mensagem de entrada possa conter dados desnecessários. Os valores estranhos são armazenados e retornados pelo WCF e, portanto, resultam no envio de mensagens inválidas para o esquema. Para evitar esse problema, o recurso de ida e volta deve ser desativado. Há duas maneiras de fazer isso.
Não implemente a IExtensibleDataObject interface em nenhum dos seus tipos.
Aplique um atributo ServiceBehaviorAttribute ao seu contrato de serviço e defina a propriedade IgnoreExtensionDataObject para
true.
Para saber mais sobre a viagem de ida e volta, confira Contratos de dados compatíveis com versões posteriores.
Controle de versão quando a validação de esquema não é necessária
A conformidade estrita do esquema raramente é necessária. Muitas plataformas toleram elementos extras não descritos por um esquema. Desde que isso seja tolerado, o conjunto completo de recursos descritos no Controle de Versão do Contrato de Dados e Forward-Compatible Contratos de Dados pode ser usado. As diretrizes a seguir são recomendadas.
Algumas das diretrizes devem ser seguidas exatamente para enviar novas versões de um tipo em que uma mais antiga é esperada ou enviar uma antiga em que a nova seja esperada. Outras diretrizes não são estritamente necessárias, mas estão listadas aqui porque podem ser afetadas pelo futuro do controle de versão do esquema.
Não tente fazer o controle de versão dos contratos de dados por herança de tipo. Para criar versões posteriores, altere o contrato de dados em um tipo existente ou crie um novo tipo não relacionado.
O uso da herança junto com os contratos de dados é permitido, desde que a herança não seja usada como um mecanismo de controle de versão e que determinadas regras sejam seguidas. Se um tipo derivar de um determinado tipo base, não o faça derivar de um tipo base diferente em uma versão futura (a menos que tenha o mesmo contrato de dados). Há uma exceção: você pode inserir um tipo na hierarquia entre um tipo de contrato de dados e seu tipo base, mas somente se ele não contiver membros de dados com os mesmos nomes que outros membros em quaisquer versões possíveis dos outros tipos na hierarquia. Em geral, o uso de membros de dados com os mesmos nomes em diferentes níveis da mesma hierarquia de herança pode levar a sérios problemas de controle de versão e deve ser evitado.
Começando com a primeira versão de um contrato de dados, sempre implemente IExtensibleDataObject para habilitar a viagem de ida e volta. Para obter mais informações, consulte Forward-Compatible Data Contracts. Se você lançou uma ou mais versões de um tipo sem implementar essa interface, implemente-a na próxima versão do tipo.
Em versões posteriores, não altere o nome ou o namespace do contrato de dados. Se estiver alterando o nome ou o namespace do tipo subjacente ao contrato de dados, certifique-se de preservar o nome e o namespace do contrato de dados usando os mecanismos apropriados, como a Name propriedade do DataContractAttribute. Para obter mais informações sobre a nomenclatura, consulte Nomes de Contrato de Dados.
Em versões posteriores, não altere os nomes de nenhum membro de dados. Se alterar o nome do campo, da propriedade ou do evento subjacente ao membro de dados, use a propriedade
Namedo DataMemberAttribute para preservar o nome do membro de dados existente.Em versões posteriores, não altere o tipo de campo, propriedade ou evento subjacente a um membro de dados, de modo que o contrato de dados resultante para esse membro de dados seja alterado. Tenha em mente que os tipos de interface são equivalentes a Object para os fins de determinação do contrato de dados esperado.
Em versões posteriores, não altere a ordem dos membros de dados existentes ajustando a Order propriedade do DataMemberAttribute atributo.
Em versões posteriores, novos membros de dados podem ser adicionados. Eles devem sempre seguir estas regras:
A IsRequired propriedade sempre deve ser deixada no valor padrão de
false.Se um valor padrão igual a
nullou zero do membro for inaceitável, um método de retorno de chamada deverá ser fornecido usando o OnDeserializingAttribute para fornecer um padrão razoável, caso o membro não esteja presente no fluxo de entrada. Para obter mais informações sobre o retorno de chamada, confira Retornos de chamada de serialização tolerantes à versão.A DataMemberAttribute.Order propriedade deve ser usada para garantir que todos os membros de dados recém-adicionados apareçam após os membros de dados existentes. A maneira recomendada de fazer isso é a seguinte: nenhum dos membros de dados na primeira versão do contrato de dados deve ter suas
Orderpropriedades definidas. Todos os membros de dados adicionados na versão 2 do contrato de dados devem ter suaOrderpropriedade definida como 2. Todos os membros de dados adicionados na versão 3 do contrato de dados devem ter seuOrderconfigurado para 3, e assim por diante. É permitido ter mais de um membro de dados definido com o mesmo número deOrder.
Não remova membros de dados em versões posteriores, mesmo que a propriedade IsRequired tenha sido deixada em seu valor padrão em versões anteriores
false.Não altere a
IsRequiredpropriedade de nenhum membro de dados existente entre versões.Para os membros de dados necessários (em que
IsRequiredétrue), não altere a propriedadeEmitDefaultValuede versão para versão.Não tente criar hierarquias de controle de versão ramificadas. Ou seja, sempre deve haver um caminho em pelo menos uma direção de qualquer versão para qualquer outra versão usando apenas as alterações permitidas por essas diretrizes.
Por exemplo, se a versão 1 de um contrato de dados Pessoa contiver apenas o membro de dados Nome, você não deverá criar a versão 2a do contrato adicionando apenas o membro Idade e a versão 2b adicionando apenas o membro Endereço. Ir de 2a a 2b envolveria a remoção da Idade e a adição de Endereço; ir na outra direção implicaria a remoção do Endereço e a adição da Idade. A remoção de membros não é permitida por essas diretrizes.
Geralmente, você não deve criar novos subtipos de tipos de contrato de dados existentes em uma nova versão do aplicativo. Da mesma forma, você não deve criar novos contratos de dados que são usados no lugar de membros de dados declarados como Objeto ou como tipos de interface. A criação dessas novas classes só é permitida quando você sabe que pode adicionar os novos tipos à lista de tipos conhecidos de todas as instâncias do seu aplicativo antigo. Por exemplo, na versão 1 do seu aplicativo, você pode ter o tipo de contrato de dados LibraryItem com os subtipos de contrato de dados Book e Newspaper. LibraryItem teria então uma lista de tipos conhecidos que contém Livro e Jornal. Suponha que agora você adicione um tipo de Revista na versão 2, que é um subtipo de LibraryItem. Se você enviar uma instância de Magazine da versão 2 para a versão 1, o contrato de dados Magazine não será encontrado na lista de tipos conhecidos e uma exceção será gerada.
Você não deve adicionar ou remover membros de enumeração entre versões. Você também não deve renomear membros de enumeração, a menos que use a propriedade Name no atributo
EnumMemberAttributepara manter seus nomes no modelo de contrato de dados inalterados.As coleções são intercambiáveis no modelo de contrato de dados, conforme descrito em Tipos de Coleta em Contratos de Dados. Isso permite um grande grau de flexibilidade. No entanto, certifique-se de que você não altere inadvertidamente um tipo de coleção de uma maneira não intercambiável de versão para versão. Por exemplo, não altere de uma coleção não personalizada (ou seja, sem o atributo
CollectionDataContractAttribute) para uma coleção personalizada ou de uma coleção personalizada para uma coleção não personalizada. Além disso, não altere as propriedades noCollectionDataContractAttributede versão para a versão. A única alteração permitida será adicionar uma propriedade Name ou Namespace se o nome ou o namespace do tipo de coleção subjacente tiver sido alterado e você precisar tornar o nome e o namespace do contrato de dados o mesmo que em uma versão anterior.
Algumas das diretrizes listadas aqui podem ser ignoradas com segurança quando as circunstâncias especiais se aplicam. Certifique-se de entender completamente os mecanismos de serialização, desserialização e esquema envolvidos antes de se desviar das diretrizes.
Consulte também
- Name
- DataContractAttribute
- Order
- IsRequired
- IExtensibleDataObject
- ServiceBehaviorAttribute
- ExtensionData
- ExtensionDataObject
- OnDeserializingAttribute
- Usando contratos de dados
- Controle de versão do contrato de dados
- Nomes de contrato de dados
- Forward-Compatible Contratos de Dados
- Retornos de chamada de serialização tolerantes à versão