Aanbevolen procedures: Versiebeheer van gegevenscontract
In dit onderwerp vindt u de aanbevolen procedures voor het maken van gegevenscontracten die in de loop van de tijd eenvoudig kunnen worden ontwikkeld. Zie de onderwerpen in Data Contracts gebruiken voor meer informatie over gegevenscontracten.
Opmerking over schemavalidatie
Bij het bespreken van versiebeheer voor gegevenscontracten is het belangrijk te weten dat het datacontractschema dat door Windows Communication Foundation (WCF) wordt geëxporteerd, geen ondersteuning voor versiebeheer heeft, behalve het feit dat elementen standaard als optioneel zijn gemarkeerd.
Dit betekent dat zelfs het meest voorkomende versiebeheerscenario, zoals het toevoegen van een nieuw gegevenslid, niet kan worden geïmplementeerd op een manier die naadloos is met betrekking tot een bepaald schema. De nieuwere versies van een gegevenscontract (bijvoorbeeld met een nieuw gegevenslid) valideren niet met behulp van het oude schema.
Er zijn echter veel scenario's waarin strikte schemacompatibiliteit niet vereist is. Veel webservicesplatformen, waaronder WCF- en XML-webservices die zijn gemaakt met ASP.NET, voeren standaard geen schemavalidatie uit en tolereren daarom extra elementen die niet door het schema worden beschreven. Wanneer u met dergelijke platforms werkt, zijn veel versiebeheerscenario's eenvoudiger te implementeren.
Er zijn dus twee sets richtlijnen voor versiebeheer van gegevenscontracten: één set voor scenario's waarbij strikte geldigheid van het schema belangrijk is en een andere set voor scenario's wanneer dat niet het geval is.
Versiebeheer wanneer schemavalidatie is vereist
Als strikte schemavalidatie vereist is in alle richtingen (nieuw-op-oud en oud-naar-nieuw), moeten gegevenscontracten als onveranderbaar worden beschouwd. Als versiebeheer vereist is, moet er een nieuw gegevenscontract worden gemaakt, met een andere naam of naamruimte, en moet het servicecontract met behulp van het gegevenstype dienovereenkomstig worden geversied.
Een servicecontract PoProcessing
voor de verwerking van inkooporders met een PostPurchaseOrder
bewerking gebruikt bijvoorbeeld een parameter die voldoet aan een PurchaseOrder
gegevenscontract. Als het PurchaseOrder
contract moet worden gewijzigd, moet u een nieuw gegevenscontract maken, dat wil zeggen, PurchaseOrder2
met daarin de wijzigingen. Vervolgens moet u de versiebeheer op servicecontractniveau afhandelen. Bijvoorbeeld door een PostPurchaseOrder2
bewerking te maken die de PurchaseOrder2
parameter gebruikt of door een PoProcessing2
servicecontract te maken waarin de PostPurchaseOrder
bewerking een PurchaseOrder2
gegevenscontract gebruikt.
Houd er rekening mee dat wijzigingen in gegevenscontracten waarnaar wordt verwezen door andere gegevenscontracten, ook worden uitgebreid naar de servicemodellaag. In het vorige scenario hoeft het PurchaseOrder
gegevenscontract bijvoorbeeld niet te worden gewijzigd. Het bevat echter een gegevenslid van een Customer
gegevenscontract, dat op zijn beurt een gegevenslid van het Address
gegevenscontract bevat, dat wel moet worden gewijzigd. In dat geval moet u een Address2
gegevenscontract maken met de vereiste wijzigingen, een Customer2
gegevenscontract dat het Address2
gegevenslid bevat en een PurchaseOrder2
gegevenscontract dat een Customer2
gegevenslid bevat. Net als in het vorige geval moet het servicecontract ook worden geversied.
Hoewel in deze voorbeelden namen worden gewijzigd (door een '2' toe te voegen), is het raadzaam om naamruimten te wijzigen in plaats van namen door nieuwe naamruimten toe te voegen met een versienummer of een datum. Het gegevenscontract wordt bijvoorbeeld http://schemas.contoso.com/2005/05/21/PurchaseOrder
gewijzigd in het http://schemas.contoso.com/2005/10/14/PurchaseOrder
gegevenscontract.
Zie Aanbevolen procedures voor serviceversiebeheer voor meer informatie.
Af en toe moet u strikte schemanaleving garanderen voor berichten die door uw toepassing worden verzonden, maar u kunt niet vertrouwen op de binnenkomende berichten om strikt schema-compatibel te zijn. In dit geval bestaat er een gevaar dat een binnenkomend bericht overbodige gegevens kan bevatten. De overbodige waarden worden opgeslagen en geretourneerd door WCF en leiden er dus toe dat schema-ongeldige berichten worden verzonden. Om dit probleem te voorkomen, moet de retourfunctie worden uitgeschakeld. Er zijn twee manieren om dit te doen.
Implementeer de IExtensibleDataObject interface niet op een van uw typen.
Pas een ServiceBehaviorAttribute kenmerk toe op uw servicecontract met de IgnoreExtensionDataObject eigenschap ingesteld op
true
.
Zie Forward-Compatible Data Contracts voor meer informatie over round-tripping.
Versiebeheer wanneer schemavalidatie niet vereist is
Strikte schemacompatibiliteit is zelden vereist. Veel platforms verdragen extra elementen die niet worden beschreven door een schema. Zolang dit wordt getolereerd, kan de volledige set functies die worden beschreven in Data Contract Versioning en Forward-Compatible Data Contracts worden gebruikt. De volgende richtlijnen worden aanbevolen.
Sommige van de richtlijnen moeten exact worden gevolgd om nieuwe versies van een type te verzenden waarvan een oudere wordt verwacht of een oude te verzenden waar de nieuwe wordt verwacht. Andere richtlijnen zijn niet strikt vereist, maar worden hier vermeld omdat ze mogelijk worden beïnvloed door de toekomst van schemaversiebeheer.
Probeer geen versie van gegevenscontracten te maken op basis van overname van het type. Als u latere versies wilt maken, wijzigt u het gegevenscontract voor een bestaand type of maakt u een nieuw niet-gerelateerd type.
Het gebruik van overname in combinatie met gegevenscontracten is toegestaan, mits overname niet wordt gebruikt als versiebeheermechanisme en dat bepaalde regels worden gevolgd. Als een type is afgeleid van een bepaald basistype, moet u het niet afleiden van een ander basistype in een toekomstige versie (tenzij het hetzelfde gegevenscontract heeft). Er is één uitzondering hierop: u kunt een type invoegen in de hiërarchie tussen een gegevenscontracttype en het basistype ervan, maar alleen als deze geen gegevensleden bevat met dezelfde namen als andere leden in mogelijke versies van de andere typen in de hiërarchie. Over het algemeen kan het gebruik van gegevensleden met dezelfde namen op verschillende niveaus van dezelfde overnamehiërarchie leiden tot ernstige problemen met versiebeheer en moeten worden vermeden.
Vanaf de eerste versie van een gegevenscontract moet u altijd implementeren IExtensibleDataObject om roundtripping mogelijk te maken. Zie Forward-Compatible Data Contracts voor meer informatie. Als u een of meer versies van een type hebt uitgebracht zonder deze interface te implementeren, implementeert u deze in de volgende versie van het type.
Wijzig in latere versies de naam of naamruimte van het gegevenscontract niet. Als u de naam of naamruimte van het type onder het gegevenscontract wijzigt, moet u de naam en naamruimte van het gegevenscontract behouden met behulp van de juiste mechanismen, zoals de Name eigenschap van het DataContractAttributegegevenscontract. Zie Namen van gegevenscontract voor meer informatie over naamgeving.
Wijzig in latere versies de namen van gegevensleden niet. Als u de naam van het veld, de eigenschap of de gebeurtenis die onder het gegevenslid ligt, wijzigt, gebruikt u de
Name
eigenschap van de eigenschap van het DataMemberAttribute gegevenslid om de bestaande naam van het gegevenslid te behouden.Wijzig in latere versies niet het type van een veld, eigenschap of gebeurtenis die onder een gegevenslid ligt, zodat het resulterende gegevenscontract voor dat gegevenslid wordt gewijzigd. Houd er rekening mee dat interfacetypen gelijk zijn aan Object voor het bepalen van het verwachte gegevenscontract.
Wijzig in latere versies de volgorde van de bestaande gegevensleden niet door de Order eigenschap van het DataMemberAttribute kenmerk aan te passen.
In latere versies kunnen nieuwe gegevensleden worden toegevoegd. Ze moeten altijd de volgende regels volgen:
De IsRequired eigenschap moet altijd op de standaardwaarde van
false
.Als een standaardwaarde van
null
of nul voor het lid onaanvaardbaar is, moet een callback-methode worden opgegeven met behulp van de OnDeserializingAttribute methode om een redelijke standaardwaarde te bieden voor het geval het lid niet aanwezig is in de binnenkomende stroom. Zie Callbacks voor versietolerante serialisatie voor meer informatie over de callback.De DataMemberAttribute.Order eigenschap moet worden gebruikt om ervoor te zorgen dat alle nieuw toegevoegde gegevensleden worden weergegeven na de bestaande gegevensleden. De aanbevolen manier om dit te doen is als volgt: geen van de gegevensleden in de eerste versie van het gegevenscontract moet hun
Order
eigenschappen hebben ingesteld. Alle gegevensleden die zijn toegevoegd in versie 2 van het gegevenscontract, moeten hunOrder
eigenschap hebben ingesteld op 2. Alle gegevensleden die zijn toegevoegd in versie 3 van het gegevenscontract, moeten zijnOrder
ingesteld op 3, enzovoort. Het is toegestaan om meer dan één gegevenslid te laten instellen op hetzelfdeOrder
getal.
Verwijder geen gegevensleden in latere versies, zelfs niet als de eigenschap in eerdere versies op de standaardeigenschap van
false
de IsRequired eigenschap is gelaten.Wijzig de
IsRequired
eigenschap van bestaande gegevensleden niet van versie naar versie.Wijzig de
EmitDefaultValue
eigenschap niet van versie in versie voor vereiste gegevensleden (waar datIsRequired
wel istrue
).Probeer geen vertakkingshiërarchieën voor versiebeheer te maken. Dat wil gezegd, er moet altijd een pad in ten minste één richting zijn van elke versie naar een andere versie met alleen de wijzigingen die door deze richtlijnen zijn toegestaan.
Als bijvoorbeeld versie 1 van een persoonsgegevenscontract alleen het lid Naamgegevens bevat, moet u versie 2a van het contract niet maken en alleen het lid Leeftijd en versie 2b toevoegen. Als u van 2a naar 2b gaat, moet u leeftijd verwijderen en adres toevoegen; In de andere richting zou het verwijderen van adres en het toevoegen van leeftijd inhouden. Leden verwijderen is niet toegestaan door deze richtlijnen.
Over het algemeen moet u geen nieuwe subtypen maken van bestaande gegevenscontracttypen in een nieuwe versie van uw toepassing. Op dezelfde manier moet u geen nieuwe gegevenscontracten maken die worden gebruikt in plaats van gegevensleden die zijn gedeclareerd als Object of als interfacetypen. Het maken van deze nieuwe klassen is alleen toegestaan wanneer u weet dat u de nieuwe typen kunt toevoegen aan de lijst met bekende typen van alle exemplaren van uw oude toepassing. In versie 1 van uw toepassing hebt u bijvoorbeeld het gegevenscontracttype LibraryItem met de subtypen Boek- en Krant-gegevenscontract. LibraryItem zou dan een lijst met bekende typen hebben die Boek en Krant bevat. Stel dat u nu een tijdschrifttype toevoegt in versie 2. Dit is een subtype van LibraryItem. Als u een Magazine-exemplaar verzendt van versie 2 naar versie 1, wordt het datacontract van Magazine niet gevonden in de lijst met bekende typen en wordt er een uitzondering gegenereerd.
U mag geen opsommingsleden toevoegen of verwijderen tussen versies. U moet ook de naam van opsommingsleden niet wijzigen, tenzij u de eigenschap Naam op het
EnumMemberAttribute
kenmerk gebruikt om hun namen in het gegevenscontractmodel hetzelfde te houden.Verzamelingen zijn uitwisselbaar in het gegevenscontractmodel, zoals beschreven in verzamelingstypen in gegevenscontracten. Dit maakt een grote mate van flexibiliteit mogelijk. Zorg er echter voor dat u een verzamelingstype niet per ongeluk wijzigt op een niet-uitwisselbare manier van versie naar versie. Wijzig bijvoorbeeld niet van een niet-aangepaste verzameling (dat wil gezegd, zonder het
CollectionDataContractAttribute
kenmerk) in een aangepaste verzameling of een aangepaste verzameling in een niet-aangepaste verzameling. Wijzig ook niet de eigenschappen van deCollectionDataContractAttribute
versie in versie. De enige toegestane wijziging is het toevoegen van een naam- of naamruimteeigenschap als de naam of naamruimte van het onderliggende verzamelingstype is gewijzigd en u de naam en naamruimte van het gegevenscontract hetzelfde moet maken als in een vorige versie.
Sommige van de hier vermelde richtlijnen kunnen veilig worden genegeerd wanneer er speciale omstandigheden van toepassing zijn. Zorg ervoor dat u de serialisatie-, deserialisatie- en schemamechanismen volledig begrijpt voordat u afwijkt van de richtlijnen.
Zie ook
- Name
- DataContractAttribute
- Order
- IsRequired
- IExtensibleDataObject
- ServiceBehaviorAttribute
- ExtensionData
- ExtensionDataObject
- OnDeserializingAttribute
- Gegevenscontracten gebruiken
- Versiebeheer van gegevenscontract
- Namen van gegevenscontract
- Doorsturen compatibele gegevenscontracten
- Callbacks voor serialisatie van versietolerante