DatenvertragsversionsverwaltungData Contract Versioning

Durch die Weiterentwicklung der Anwendungen müssen Sie möglicherweise auch die Datenverträge ändern, die die Dienste verwenden.As applications evolve, you may also have to change the data contracts the services use. Dieses Thema erklärt, wie man die Versionsverwaltung von Datenverträgen durchführt.This topic explains how to version data contracts. In diesem Thema werden die Datenvertragsversionsmechanismen beschrieben.This topic describes the data contract versioning mechanisms. Eine vollständige Übersicht und normative versionsverwaltungsanleitung finden Sie unter Vorgehensweisen: versionsverwaltung von Datenverträgen.For a complete overview and prescriptive versioning guidance, see Best Practices: Data Contract Versioning.

Breaking Changes gegenüber Non-breaking ChangesBreaking vs. Nonbreaking Changes

Änderungen an einem Datenvertrag können "breaking" oder "non-breaking" sein.Changes to a data contract can be breaking or nonbreaking. Wird ein Datenvertrag auf eine "non-breaking"-Art geändert, kann eine Anwendung, die die ältere Version des Vertrags verwendet, mit einer Anwendung kommunizieren, die die neuere Version verwendet; und eine Anwendung, die die neuere Version des Vertrags verwendet, kann mit einer Anwendung kommunizieren, die die ältere Version verwendet.When a data contract is changed in a nonbreaking way, an application using the older version of the contract can communicate with an application using the newer version, and an application using the newer version of the contract can communicate with an application using the older version. Andererseits verhindert ein "Breaking Change" die Kommunikation in eine oder beide Richtungen.On the other hand, a breaking change prevents communication in one or both directions.

Jede Änderung eines Typs, der nicht beeinflusst, wie er gesendet und empfangen wird, ist "non-breaking".Any changes to a type that do not affect how it is transmitted and received are nonbreaking. Solche Änderungen ändern nicht den Datenvertrag, nur den zugrunde liegenden Typ.Such changes do not change the data contract, only the underlying type. Beispielsweise kann der Name eines Felds auf "non-breaking"-Art geändert werden, indem die Eigenschaft Name des DataMemberAttribute auf den älteren Versionsnamen festgelegt wird.For example, you can change the name of a field in a nonbreaking way if you then set the Name property of the DataMemberAttribute to the older version name. Der folgende Code zeigt Version 1 eines Datenvertrags.The following code shows version 1 of a data contract.

// Version 1
[DataContract]
public class Person
{
    [DataMember]
    private string Phone;
}
' Version 1
<DataContract()>  _
Public Class Person
    <DataMember()>  _
    Private Phone As String
End Class 

Im folgenden Code wird ein "Non-Breaking Change" veranschaulicht.The following code shows a nonbreaking change.

// Version 2. This is a non-breaking change because the data contract 
// has not changed, even though the type has.
[DataContract]
public class Person
{
    [DataMember(Name = "Phone")]
    private string Telephone;
}
' Version 2. This is a non-breaking change because the data contract 
' has not changed, even though the type has.
<DataContract()>  _
Public Class Person
    <DataMember(Name := "Phone")>  _
    Private Telephone As String
End Class 

Einige Änderungen ändern die gesendeten Daten, müssen aber nicht unbedingt "breaking" sein.Some changes do modify the transmitted data, but may or may not be breaking. Die folgenden Änderungen sind immer "breaking":The following changes are always breaking:

  • Das Ändern der Werte Nameoder Namespace eines Datenvertrags.Changing the Name or Namespace value of a data contract.

  • Das Ändern der Reihenfolge der Datenelemente über die Eigenschaft Order der Klasse DataMemberAttribute.Changing the order of data members by using the Order property of the DataMemberAttribute.

  • Das Umbenennen eines Datenelements.Renaming a data member.

  • Das Ändern des Datenvertrags eines Datenelements.Changing the data contract of a data member. Beispielsweise die Änderung des Typs eines Datenelements von ganzer Zahl zu Zeichenfolge oder von einem Typ mit Datenvertrag namens "Kunde" in einen Typ mit einem Datenvertrag namens "Person".For example, changing the type of data member from an integer to a string, or from a type with a data contract named "Customer" to a type with a data contract named "Person".

Ebenfalls möglich sind die folgenden Änderungen.The following changes are also possible.

Das Hinzufügen und Entfernen von DatenelementenAdding and Removing Data Members

In den meisten Fällen ist das Hinzufügen oder Entfernen eines Datenelements kein "Breaking Change", sofern keine strikte Schemavalidierung (neue Instanzen, die gegen das alte Schema validiert werden) erforderlich ist.In most cases, adding or removing a data member is not a breaking change, unless you require strict schema validity (new instances validating against the old schema).

Wenn ein Typ mit einem Extrafeld in einen Typ mit einem fehlenden Feld deserialisiert wird, werden die Extrainformationen ignoriert.When a type with an extra field is deserialized into a type with a missing field, the extra information is ignored. (Es kann auch sein gespeichert für Round-Tripping-Zwecke; Weitere Informationen, finden Sie unter aufwärtskompatible Datenverträge).(It may also be stored for round-tripping purposes; for more information, see Forward-Compatible Data Contracts).

Wenn ein Typ mit einem fehlenden Feld in einen Typ mit einem Extrafeld deserialisiert wird, behält das Extrafeld seinen Standardwert bei, normalerweise null.When a type with a missing field is deserialized into a type with an extra field, the extra field is left at its default value, usually zero or null. (Der Standardwert kann geändert werden; weitere Informationen finden Sie unter versionstolerante Serialisierungsrückrufe.)(The default value may be changed; for more information, see Version-Tolerant Serialization Callbacks.)

Beispielsweise können Sie die Klasse CarV1 für einen Client und die Klasse CarV2 für einen Dienst verwenden; oder Sie können die Klasse CarV1 für einen Dienst und die Klasse CarV2 für einen Client verwenden.For example, you can use the CarV1 class on a client and the CarV2 class on a service, or you can use the CarV1 class on a service and the CarV2 class on a client.

// Version 1 of a data contract, on machine V1.
[DataContract(Name = "Car")]
public class CarV1
{
    [DataMember]
    private string Model;
}

// Version 2 of the same data contract, on machine V2.
[DataContract(Name = "Car")]
public class CarV2
{
    [DataMember]
    private string Model;

    [DataMember]
    private int HorsePower;
}
' Version 1 of a data contract, on machine V1.
<DataContract(Name := "Car")>  _
Public Class CarV1
    <DataMember()>  _
    Private Model As String
End Class 

' Version 2 of the same data contract, on machine V2.
<DataContract(Name := "Car")>  _
Public Class CarV2
    <DataMember()>  _
    Private Model As String
    
    <DataMember()>  _
    Private HorsePower As Integer
End Class 

Der Version 2-Endpunkt kann Daten erfolgreich an den Version 1-Endpunkt senden.The version 2 endpoint can successfully send data to the version 1 endpoint. Eine Serialisierung von Version 2 des Car-Datenvertrags führt zu einer XML-Darstellung, die in etwa der folgenden entspricht.Serializing version 2 of the Car data contract yields XML similar to the following.

<Car>  
    <Model>Porsche</Model>  
    <HorsePower>300</HorsePower>  
</Car>  

Das Deserialisierungsmodul auf V1 findet kein entsprechendes Datenelement für das Feld HorsePower und verwirft die Daten.The deserialization engine on V1 does not find a matching data member for the HorsePower field, and discards that data.

Außerdem kann der Version 1-Endpunkt Daten erfolgreich an den Version 2-Endpunkt senden.Also, the version 1 endpoint can send data to the version 2 endpoint. Eine Serialisierung von Version 1 des Car-Datenvertrags führt zu einer der folgenden ähnlichen XML-Darstellung.Serializing version 1 of the Car data contract yields XML similar to the following.

<Car>  
    <Model>Porsche</Model>  
</Car>  

Der Version 2-Deserialisierer weiß nicht, auf was er das Feld HorsePower festlegen soll, da in der eingehenden XML keine entsprechenden Daten vorliegen.The version 2 deserializer does not know what to set the HorsePower field to, because there is no matching data in the incoming XML. Stattdessen wird das Feld auf den Standardwert 0 (null) festgelegt.Instead, the field is set to the default value of 0.

Erforderliche DatenelementeRequired Data Members

Ein Datenelement kann als "erforderlich" markiert werden, indem die Eigenschaft IsRequired der Klasse DataMemberAttribute auf true festgelegt wird.A data member may be marked as being required by setting the IsRequired property of the DataMemberAttribute to true. Wenn erforderliche Daten während der Deserialisierung fehlen, wird eine Ausnahme verwendet, anstatt die Datenelemente auf ihren Standardwert festzulegen.If required data is missing while deserializing, an exception is thrown instead of setting the data member to its default value.

Das Hinzufügen von erforderlichen Datenelementen ist ein "Breaking Change".Adding a required data member is a breaking change. Das bedeutet, dass der neuere Typ noch immer an Endpunkte mit dem älteren Typ gesendet werden kann, aber nicht umgekehrt.That is, the newer type can still be sent to endpoints with the older type, but not the other way around. Das Löschen eines Datenelements, das in einer vorherigen Version als "erforderlich" markiert war, ist ebenfalls ein "Breaking Change".Removing a data member that was marked as required in any prior version is also a breaking change.

Die Änderung des Eigenschaftswerts IsRequired von true nach false ist nicht "breaking", aber die Änderung von false nach true kann "breaking" sein, wenn eine frühere Version des Typs das fragliche Datenelement nicht besitzt.Changing the IsRequired property value from true to false is not breaking, but changing it from false to true may be breaking if any prior versions of the type do not have the data member in question.

Hinweis

Auch wenn die Eigenschaft IsRequired auf true festgelegt ist, müssen die eingehenden Daten NULL oder 0 (null) sein, und es muss ein Typ vorbereitet sein, um diese Möglichkeit abzudecken.Although the IsRequired property is set to true, the incoming data may be null or zero, and a type must be prepared to handle this possibility. IsRequired sollte nicht als Sicherheitsmechanismus zum Schutz gegen ungültige eingehende Daten verwendet werden.Do not use IsRequired as a security mechanism to protect against bad incoming data.

Ausgelassene StandardwerteOmitted Default Values

Es ist möglich (wenn auch nicht empfohlen) Festlegen der EmitDefaultValue -Eigenschaft des DataMemberAttribute-Attributs auf false, wie in beschrieben Daten Element Standardwerte.It is possible (although not recommended) to set the EmitDefaultValue property on the DataMemberAttribute attribute to false, as described in Data Member Default Values. Wenn diese Einstellung false ist, wird das Datenelement nicht ausgegeben, wenn es auf seinen Standardwert (normalerweise NULL oder 0 (null)) festgelegt ist.If this setting is false, the data member will not be emitted if it is set to its default value (usually null or zero). Dies ist in anderen Versionen auf zwei Arten nicht kompatibel mit erforderlichen Datenelementen:This is not compatible with required data members in different versions in two ways:

  • Ein Datenvertrag mit einem Datenelement, das in einer Version erforderlich ist, kann keine Standarddaten (NULL oder 0(null)) von einer anderen Version erhalten, in der das Datenelement EmitDefaultValue auf false festgelegt hat.A data contract with a data member that is required in one version cannot receive default (null or zero) data from a different version in which the data member has EmitDefaultValue set to false.

  • Ein erforderliches Datenelement, dessen EmitDefaultValue auf false festgelegt ist, kann nicht verwendet werden, um seinen Standardwert (NULL oder 0 (null)) zu deserialisieren, aber es kann bei der Deserialisierung einen derartigen Wert erhalten.A required data member that has EmitDefaultValue set to false cannot be used to serialize its default (null or zero) value, but can receive such a value on deserialization. Dies schafft ein Round-Tripping-Problem (Daten können eingelesen werden, aber die gleichen Daten können nicht ausgegeben werden).This creates a round-tripping problem (data can be read in but the same data cannot then be written out). Wenn daher in einer Version IsRequired true und EmitDefaultValue false ist, sollte die gleiche Kombination für alle anderen Versionen gelten, damit keine Version des Datenvertrags einen Wert produzieren kann, der nicht zu einem Roundtrip führt.Therefore, if IsRequired is true and EmitDefaultValue is false in one version, the same combination should apply to all other versions such that no version of the data contract would be able to produce a value that does not result in a round trip.

SchemaüberlegungenSchema Considerations

Eine Erläuterung, welche Schemas für Datenvertragstypen erstellt wird, finden Sie unter Datenvertrags-Schemareferenz.For an explanation of what schema is produced for data contract types, see Data Contract Schema Reference.

Das Schema WCF erzeugt für Datenvertragstypen macht keine Bereitstellungen für die versionsverwaltung.The schema WCF produces for data contract types makes no provisions for versioning. Das bedeutet, dass das Schema, das von einer bestimmten Version eines Typs exportiert wurde, nur diejenigen Datenelemente enthält, die in dieser Version vorliegen.That is, the schema exported from a certain version of a type contains only those data members present in that version. Die Implementierung der IExtensibleDataObject-Schnittstelle ändert nicht das Schema eines Typs.Implementing the IExtensibleDataObject interface does not change the schema for a type.

Datenelemente werden standardmäßig als optionale Elemente ins Schema exportiert.Data members are exported to the schema as optional elements by default. Dies bedeutet, dass der Wert von minOccurs (XML-Attribut) auf 0 (null) gesetzt wird.That is, the minOccurs (XML attribute) value is set to 0. Erforderliche Datenmember werden exportiert, wenn minOccurs auf 1 festgelegt wurde.Required data members are exported with minOccurs set to 1.

Viele der Änderungen, die als "non-breaking" gelten, sind tatsächlich "breaking", wenn eine strenge Einhaltung des Schemas erforderlich ist.Many of the changes considered to be nonbreaking are actually breaking if strict adherence to the schema is required. Im vorherigen Beispiel würde eine CarV1-Instanz, die nur das Element Model enthält, gegen das CarV2-Schema (das sowohl über Model als auch Horsepower verfügt, die aber beide optional sind) positiv geprüft werden.In the preceding example, a CarV1 instance with just the Model element would validate against the CarV2 schema (which has both Model and Horsepower, but both are optional). Das Gegenteil stimmt aber nicht: eine CarV2-Instanz würde keine Validierung gegen das CarV1-Schema bestehen.However, the reverse is not true: a CarV2 instance would fail validation against the CarV1 schema.

Round-Tripping bringt auch einige zusätzliche Überlegungen mit sich.Round-tripping also entails some additional considerations. Weitere Informationen finden Sie im Abschnitt "Schemaüberlegungen" aufwärtskompatible Datenverträge.For more information, see the "Schema Considerations" section in Forward-Compatible Data Contracts.

Andere zulässige ÄnderungenOther Permitted Changes

Die Implementierung der IExtensibleDataObject-Schnittstelle ist ein "Non-Breaking Change".Implementing the IExtensibleDataObject interface is a nonbreaking change. Es besteht jedoch kein Round-Tripping-Support für Versionen des Typs vor der Version, in der IExtensibleDataObject implementiert wurde.However, round-tripping support does not exist for versions of the type prior to the version in which IExtensibleDataObject was implemented. Weitere Informationen finden Sie unter Aufwärtskompatible Datenverträge.For more information, see Forward-Compatible Data Contracts.

EnumerationenEnumerations

Das Hinzufügen oder Entfernen einer Enumeration ist ein "Breaking Change".Adding or removing an enumeration member is a breaking change. Die Änderung des Namens einer Enumeration ist "breaking", sofern nicht der Vertragsname durch die Verwendung des Attributs EnumMemberAtttribute der gleiche wie in der alten Version geblieben ist.Changing the name of an enumeration member is breaking, unless its contract name is kept the same as in the old version by using the EnumMemberAtttribute attribute. Weitere Informationen finden Sie unter Enumerationstypen in Datenverträgen.For more information, see Enumeration Types in Data Contracts.

AuflistungenCollections

Die meisten Sammlungsänderungen sind "non-breaking", da die meisten Sammlungstypen im Datenvertragsmodell gegeneinander austauschbar sind.Most collection changes are nonbreaking because most collection types are interchangeable with each other in the data contract model. Eine nicht angepasste Sammlung angepasst zu machen oder umgekehrt ist jedoch ein "Breaking Change".However, making a noncustomized collection customized or vice versa is a breaking change. Außerdem ist die Änderung der Anpassungseinstellungen der Sammlung ein "Breaking Change", d. h. eine Änderung des Namens und Namespace ihres Datenvertrags und eine Wiederholung des Elementnamens, des Schlüsselelementnamens und des Wertelementnamens.Also, changing the collection's customization settings is a breaking change; that is, changing its data contract name and namespace, repeating element name, key element name, and value element name. Weitere Informationen zu sammlungsanpassung finden Sie unter Sammlungstypen in Datenverträgen.For more information about collection customization, see Collection Types in Data Contracts.
Natürlich ist die Änderung des Datenvertrags der Inhalte einer Sammlung (z. B. die Änderung von einer Liste ganzer Zahlen zu einer Liste von Zeichenfolgen) ein "Breaking Change".Naturally, changing the data contract of contents of a collection (for example, changing from a list of integers to a list of strings) is a breaking change.

Siehe auchSee Also

Name
DataMemberAttribute
Name
Namespace
Order
IsRequired
SerializationException
IExtensibleDataObject
Versionstolerante SerialisierungsrückrufeVersion-Tolerant Serialization Callbacks
Bewährte Methoden: Versionsverwaltung von DatenverträgenBest Practices: Data Contract Versioning
Verwenden von DatenverträgenUsing Data Contracts
DatenvertragsäquivalenzData Contract Equivalence
Aufwärtskompatible DatenverträgeForward-Compatible Data Contracts