Správa verzí kontraktů dat
S vývojem aplikací můžete také muset změnit kontrakty dat, které služby používají. Toto téma vysvětluje, jak verze kontraktů dat. Toto téma popisuje mechanismy správy verzí kontraktů dat. Kompletní přehled a doprovodné materiály k verzím najdete v tématu Osvědčené postupy: Správa verzí kontraktů dat.
Rozbíjející vs. nefunkční změny
Změny kontraktu dat můžou být přerušení nebo přerušení. Když se kontrakt dat změní bez porušení, aplikace používající starší verzi kontraktu může komunikovat s aplikací pomocí novější verze a aplikace používající novější verzi kontraktu může komunikovat s aplikací pomocí starší verze. Na druhé straně změna způsobující chybu zabraňuje komunikaci v jednom nebo obou směrech.
Všechny změny typu, které nemají vliv na způsob přenosu a přijetí, jsou nepřerušující. Takové změny nemění kontrakt dat, pouze základní typ. Pokud například nastavíte Name vlastnost DataMemberAttribute na název starší verze, můžete změnit název pole jiným způsobem. Následující kód ukazuje verzi 1 datového kontraktu.
// Version 1
[DataContract]
public class Person
{
[DataMember]
private string Phone;
}
' Version 1
<DataContract()> _
Public Class Person
<DataMember()> _
Private Phone As String
End Class
Následující kód ukazuje neulomenou změnu.
// 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
Některé změny mění přenášená data, ale mohou nebo nemusí být rozbíjené. Následující změny jsou vždy zásadní:
Změna pořadí datových členů pomocí Order vlastnosti DataMemberAttribute.
Přejmenování datového členu
Změna kontraktu dat datového člena Například změna typu datového členu z celého čísla na řetězec nebo z typu s datovým kontraktem s názvem "Zákazník" na typ s datovým kontraktem s názvem "Osoba".
Je také možné provést následující změny.
Přidávání a odebírání datových členů
Ve většině případů není přidání nebo odebrání datového členu zásadní změnou, pokud nevyžadujete striktní platnost schématu (nové instance validující proti starému schématu).
Pokud je typ s extra polem deserializován do typu s chybějícím polem, dodatečné informace se ignorují. (Může být také uložen pro účely odezvy; další informace najdete v tématu Kontrakty dat kompatibilní s předáváním).
Pokud je typ s chybějícím polem deserializován do typu s dodatečným polem, pole navíc zůstane na výchozí hodnotě, obvykle nula nebo null
. (Výchozí hodnota může být změněna. Další informace najdete v tématu Zpětné volání serializace odolné proti verzím.)
Třídu můžete například použít CarV1
v klientovi a CarV2
třídě ve službě nebo můžete třídu použít CarV1
ve službě a CarV2
třídu na klientovi.
// 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
Koncový bod verze 2 může úspěšně odesílat data do koncového bodu verze 1. Serializace verze 2 datového kontraktu Car
přináší kód XML podobný následujícímu.
<Car>
<Model>Porsche</Model>
<HorsePower>300</HorsePower>
</Car>
Modul deserializace na V1 nenajde odpovídající datový člen pole HorsePower
a tato data zahodí.
Koncový bod verze 1 může také odesílat data do koncového bodu verze 2. Serializace verze 1 datového kontraktu Car
přináší kód XML podobný následujícímu.
<Car>
<Model>Porsche</Model>
</Car>
Deserializátor verze 2 neví, na co nastavit HorsePower
pole, protože v příchozím XML nejsou žádná odpovídající data. Místo toho je pole nastaveno na výchozí hodnotu 0.
Požadované datové členy
Datový člen může být označen jako povinný nastavením IsRequired vlastnosti DataMemberAttribute na true
hodnotu . Pokud při deserializaci chybí požadovaná data, vyvolá se výjimka místo nastavení datového členu na výchozí hodnotu.
Přidání požadovaného datového členu je zásadní změna. To znamená, že novější typ se dá dál odesílat do koncových bodů se starším typem, ale ne naopak. Odebrání datového členu označeného jako povinného v jakékoli předchozí verzi je také zásadní změnou.
IsRequired Změna hodnoty vlastnosti z true
na false
není zásadní, ale změna z false
hodnoty na true
může být zásadní, pokud některé předchozí verze typu nemají příslušného datového člena.
Poznámka:
I když je vlastnost nastavena IsRequiredtrue
, příchozí data mohou být null nebo nula a typ musí být připraven pro zpracování této možnosti. Nepoužívejte IsRequired jako bezpečnostní mechanismus k ochraně před špatnými příchozími daty.
Vynechané výchozí hodnoty
Je možné (i když se nedoporučuje) nastavit EmitDefaultValue
vlastnost u atributu DataMemberAttribute na false
, jak je popsáno v výchozích hodnotách datového členu. Pokud je toto nastavení nastaveno false
, datový člen se nevygeneruje, pokud je nastavená na výchozí hodnotu (obvykle null nebo nula). To není kompatibilní s požadovanými datovými členy v různých verzích dvěma způsoby:
Kontrakt dat s datovým členem, který je vyžadován v jedné verzi, nemůže přijímat výchozí (null nebo nula) data z jiné verze, ve které je
EmitDefaultValue
datový člen nastaven nafalse
.Požadovaný datový člen, který má
EmitDefaultValue
nastavenou hodnotufalse
, nelze použít k serializaci výchozí hodnoty (null nebo nula), ale může takovou hodnotu přijmout při deserializaci. Tím se vytvoří problém s odezvou (data se dají číst, ale stejná data se pak nedají zapsat). Proto pokudIsRequired
je aEmitDefaultValue
jetrue
false
v jedné verzi, měla by stejná kombinace platit pro všechny ostatní verze, aby žádná verze datového kontraktu nemohla vytvořit hodnotu, která by nezpůsobovala odezvu.
Důležité informace o schématu
Vysvětlení toho, jaké schéma se vytváří pro typy datových kontraktů, naleznete v tématu Referenční informace ke schématu kontraktu dat.
Wcf schématu vytváří pro typy kontraktů dat žádná ustanovení pro správu verzí. To znamená, že schéma exportované z určité verze typu obsahuje pouze ty datové členy, které jsou v této verzi. IExtensibleDataObject Implementace rozhraní nezmění schéma pro typ.
Datové členy se ve výchozím nastavení exportují do schématu jako volitelné prvky. To znamená, že minOccurs
hodnota (atribut XML) je nastavena na 0. Požadované datové členy se exportují s nastavenou minOccurs
na hodnotu 1.
Mnoho změn, které se považují za neprolomné, je ve skutečnosti zásadní, pokud je vyžadováno přísné dodržování schématu. V předchozím příkladu CarV1
by instance s pouze Model
elementem ověřila vůči schématu CarV2
(který má obě Model
i Horsepower
, ale oba jsou volitelné). Opačná hodnota však není pravdivá: CarV2
Instance by selhala ověření schématu CarV1
.
Součástí náběhů je také několik dalších aspektů. Další informace najdete v části Aspekty schématu v kontraktech dat kompatibilních s předáváním.
Jiné povolené změny
IExtensibleDataObject Implementace rozhraní je neprolomná změna. Podpora odezvy však neexistuje pro verze typu před verzí, ve které IExtensibleDataObject byla implementována. Další informace najdete v tématu Kontrakty dat kompatibilní s předáváním.
Výčty
Přidání nebo odebrání člena výčtu je zásadní změna. Změna názvu člena výčtu se přeruší, pokud jeho název kontraktu není zachován stejně jako ve staré verzi pomocí atributu EnumMemberAttribute
. Další informace naleznete v tématu Výčtové typy v kontraktech dat.
Kolekce
Většina změn kolekce je neprolomná, protože většina typů kolekcí je vzájemně zaměnitelná v modelu kontraktu dat. Přizpůsobení kolekce, která není přizpůsobená nebo naopak, je však zásadní změnou. Změna nastavení přizpůsobení kolekce je také zásadní změnou; to znamená, že změna názvu kontraktu dat a oboru názvů, opakující se název elementu, název klíčového elementu a název prvku hodnoty. Další informace o přizpůsobení kolekce naleznete v tématu Typy kolekcí v kontraktech dat.
Změna datového kontraktu obsahu kolekce (například změna ze seznamu celých čísel na seznam řetězců) je zásadní změnou.