Typy XML i ADO.NET w kontraktach danych

Model kontraktu danych programu Windows Communication Foundation (WCF) obsługuje niektóre typy reprezentujące kod XML bezpośrednio. Gdy te typy są serializowane do formatu XML, serializator zapisuje zawartość XML tych typów bez dalszego przetwarzania. Obsługiwane typy to XmlElement, tablice XmlNode (ale nie XmlNode sam typ), a także typy, które implementują IXmlSerializable. Typ DataSet i DataTable , a także typ zestawów danych, są często używane w programowaniu bazy danych. Te typy implementują IXmlSerializable interfejs i dlatego można serializować w modelu kontraktu danych. Niektóre specjalne zagadnienia dotyczące tych typów są wymienione na końcu tego tematu.

Typy XML

Xml, element

Typ XmlElement jest serializowany przy użyciu jego zawartości XML. Na przykład użyj następującego typu.

[DataContract(Namespace=@"http://schemas.contoso.com")]
public class MyDataContract
{
    [DataMember]
    public XmlElement myDataMember;
    public void TestClass()
    {
        XmlDocument xd = new XmlDocument();
        myDataMember = xd.CreateElement("myElement");
        myDataMember.InnerText = "myContents";
        myDataMember.SetAttribute
         ("myAttribute","myValue");
    }
}
<DataContract([Namespace]:="http://schemas.contoso.com")> _
Public Class MyDataContract
    <DataMember()> _
    Public myDataMember As XmlElement

    Public Sub TestClass()
        Dim xd As New XmlDocument()
        myDataMember = xd.CreateElement("myElement")
        myDataMember.InnerText = "myContents"
        myDataMember.SetAttribute("myAttribute", "myValue")

    End Sub
End Class

Jest to serializowane do kodu XML w następujący sposób:

<MyDataContract xmlns="http://schemas.contoso.com">  
    <myDataMember>  
        <myElement xmlns="" myAttribute="myValue">  
            myContents  
        </myElement>  
    </myDataMember>  
</MyDataContract>  

Zwróć uwagę, że element <myDataMember> członkowski danych otoki jest nadal obecny. Nie ma możliwości usunięcia tego elementu w modelu kontraktu danych. Serializatory obsługujące ten model (i DataContractSerializerNetDataContractSerializer) mogą emitować specjalne atrybuty do tego elementu otoki. Te atrybuty obejmują standardowy atrybut "nil" wystąpienia schematu XML (co pozwala XmlElementnullna wartość ) i atrybut "type" (co pozwala XmlElement na stosowanie polimorficznie). Ponadto następujące atrybuty XML są specyficzne dla programu WCF: "Id", "Ref", "Type" i "Assembly". Te atrybuty mogą być emitowane do obsługi przy użyciu XmlElement z włączonym trybem zachowywania grafu obiektów lub za pomocą .NetDataContractSerializer (Aby uzyskać więcej informacji na temat trybu zachowywania grafu obiektów, zobacz Serializacja i deserializacja).

Tablice lub kolekcje XmlElement obiektów są dozwolone i są obsługiwane jako każda inna tablica lub kolekcja. Oznacza to, że istnieje element otoki dla całej kolekcji i oddzielny element otoki (podobny do <myDataMember> w poprzednim przykładzie) dla każdego XmlElement elementu w tablicy.

W przypadku deserializacji XmlElement element jest tworzony przez deserializator z przychodzącego kodu XML. Prawidłowy element nadrzędny XmlDocument jest dostarczany przez deserializator.

Upewnij się, że fragment XML, który jest deserializowany do definiuje XmlElement wszystkie prefiksy używane i nie opiera się na żadnych definicjach prefiksów z elementów modułu ancestor. Jest to problem tylko w przypadku używania elementu DataContractSerializer w celu uzyskania dostępu do kodu XML z innego źródła (innego niżDataContractSerializer).

W przypadku użycia z elementem DataContractSerializerelement XmlElement może być przypisany polimorficznie, ale tylko do składowej danych typu Object. Mimo że implementuje IEnumerableelement , XmlElement nie można go użyć jako typu kolekcji i nie można go przypisać do IEnumerable elementu członkowskiego danych. Podobnie jak w przypadku wszystkich przypisań polimorficznych, DataContractSerializer funkcja emituje nazwę kontraktu danych w wynikowym kodzie XML. W takim przypadku jest to "XmlElement" w http://schemas.datacontract.org/2004/07/System.Xml przestrzeni nazw.

W przypadku parametru NetDataContractSerializerXmlElement obsługiwane jest dowolne prawidłowe przypisanie polimorficzne (do Object lub IEnumerable).

Nie należy próbować używać dowolnego z seriizatorów z typami pochodzącymi z XmlElementklasy , niezależnie od tego, czy są przypisane polimorficznie, czy nie.

Tablica xmlnode

Użycie tablic obiektu XmlNode jest bardzo podobne do użycia polecenia XmlElement. Korzystanie z tablic z XmlNode zapewnia większą elastyczność niż użycie metody XmlElement. Można napisać wiele elementów wewnątrz elementu opakowującego składowe danych. Możesz również wstrzyknąć zawartość inną niż elementy wewnątrz elementu opakowującego składowe danych, takie jak komentarze XML. Na koniec można umieścić atrybuty w elemencie opakowującym dane. Wszystko to można osiągnąć, wypełniając tablicę XmlNode z określonymi klasami pochodnymi XmlNode , takimi jak XmlAttribute, XmlElement lub XmlComment. Na przykład użyj następującego typu.

[DataContract(Namespace="http://schemas.contoso.com")]
public class MyDataContract
{
    [DataMember]
    public XmlNode[] myDataMember = new XmlNode[4];
    public void TestClass()
    {
        XmlDocument xd = new XmlDocument();
        XmlElement xe = xd.CreateElement("myElement");
        xe.InnerText = "myContents";
        xe.SetAttribute
         ("myAttribute","myValue");
    
        XmlAttribute atr = xe.Attributes[0];
        XmlComment cmnt = xd.CreateComment("myComment");
        
      myDataMember[0] = atr;
      myDataMember[1] = cmnt;
      myDataMember[2] = xe;
      myDataMember[3] = xe;
    }
}
<DataContract([Namespace]:="http://schemas.contoso.com")> _
Public Class MyDataContract
    <DataMember()> _
    Public myDataMember(3) As XmlNode

    Public Sub TestClass()
        Dim xd As New XmlDocument()
        Dim xe As XmlElement = xd.CreateElement("myElement")
        xe.InnerText = "myContents"
        xe.SetAttribute("myAttribute", "myValue")

        Dim atr As XmlAttribute = xe.Attributes(0)
        Dim cmnt As XmlComment = xd.CreateComment("myComment")

        myDataMember(0) = atr
        myDataMember(1) = cmnt
        myDataMember(2) = xe
        myDataMember(3) = xe

    End Sub

End Class

Po serializacji wynikowy kod XML jest podobny do poniższego kodu.

<MyDataContract xmlns="http://schemas.contoso.com">  
  <myDataMember myAttribute="myValue">  
     <!--myComment-->  
     <myElement xmlns="" myAttribute="myValue">  
 myContents  
     </myElement>  
     <myElement xmlns="" myAttribute="myValue">  
       myContents  
     </myElement>  
  </myDataMember>  
</MyDataContract>  

Należy pamiętać, że element <myDataMember> otoki składowych danych zawiera atrybut, komentarz i dwa elementy. Są to cztery XmlNode wystąpienia, które zostały serializowane.

Tablica wyników powoduje, że nie można serializować nieprawidłowego XmlNode kodu XML. Na przykład tablica dwóch XmlNode wystąpień, w których pierwszy to , XmlElement a druga jest nieprawidłowa XmlAttribute , ponieważ ta sekwencja nie odpowiada żadnemu prawidłowemu wystąpieniu XML (nie ma miejsca na dołączenie atrybutu do).

W przypadku deserializacji tablicy węzłów XmlNodesą tworzone i wypełniane informacjami z przychodzącego kodu XML. Prawidłowy element nadrzędny XmlDocument jest dostarczany przez deserializator. Wszystkie węzły są deserializowane, w tym wszystkie atrybuty elementu członkowskiego danych otoki, ale z wyłączeniem atrybutów umieszczonych tam przez serializatory WCF (takie jak atrybuty używane do wskazywania przypisania polimorficznego). Zastrzeżenie dotyczące definiowania wszystkich prefiksów przestrzeni nazw w fragmentacji XML ma zastosowanie do deserializacji tablic, XmlNode podobnie jak w przypadku deserializacji XmlElement.

W przypadku używania serializatorów z włączonym zachowywaniem grafu obiektów równość obiektów jest zachowywana tylko na poziomie XmlNode tablic, a nie poszczególnych XmlNode wystąpień.

Nie należy próbować serializować tablicy XmlNode , w której co najmniej jeden węzeł jest ustawiony na nullwartość . Dozwolone jest, aby cały element członkowski tablicy był null, ale nie dla żadnej osoby XmlNode zawartej w tablicy. Jeśli cały element członkowski tablicy ma wartość null, element członkowski danych otoki zawiera specjalny atrybut wskazujący, że ma wartość null. W przypadku deserializacji cała składowa tablicy również staje się równa null.

Tylko regularne tablice XmlNode są traktowane specjalnie przez serializator. Elementy członkowskie danych zadeklarowane jako inne typy kolekcji, które zawierają XmlNodeelementy członkowskie lub dane zadeklarowane jako tablice typów pochodzących z XmlNodeelementu , nie są traktowane specjalnie. W związku z tym zwykle nie można ich serializować, chyba że spełniają one również jedno z pozostałych kryteriów serializacji.

Tablice lub kolekcje tablic tablic XmlNode są dozwolone. Istnieje element otoki dla całej kolekcji i oddzielny element otoki (podobny do <myDataMember> w poprzednim przykładzie) dla każdej tablicy XmlNode w zewnętrznej tablicy lub kolekcji.

Wypełnianie elementu członkowskiego danych typu ArrayObject lub Array z IEnumerableXmlNode wystąpieniami nie powoduje traktowania elementu członkowskiego danych jako ArrayXmlNode wystąpienia. Każdy element członkowski tablicy jest serializowany oddzielnie.

W przypadku użycia z DataContractSerializertablicami XmlNode obiektów można przypisać polimorficznie, ale tylko do składowej danych typu Object. Mimo że implementuje IEnumerable, tablica XmlNode nie może być używana jako typ kolekcji i być przypisana IEnumerable do elementu członkowskiego danych. Podobnie jak w przypadku wszystkich przypisań polimorficznych, DataContractSerializer parametr emituje nazwę kontraktu danych w wynikowym pliku XML — w tym przypadku jest to "ArrayOfXmlNode" w http://schemas.datacontract.org/2004/07/System.Xml przestrzeni nazw. W przypadku użycia z tablicą NetDataContractSerializerXmlNode obsługiwane jest każde prawidłowe przypisanie tablicy.

Zagadnienia dotyczące schematu

Aby uzyskać szczegółowe informacje na temat mapowania schematów typów XML, zobacz Dokumentacja schematu kontraktu danych. Ta sekcja zawiera podsumowanie ważnych kwestii.

Element członkowski XmlElement typu danych jest mapowany na element zdefiniowany przy użyciu następującego typu anonimowego.

<xsd:complexType>  
   <xsd:sequence>  
      <xsd:any minOccurs="0" processContents="lax" />  
   </xsd:sequence>  
</xsd:complexType>  

Element członkowski danych typu Tablica XmlNode jest mapowany na element zdefiniowany przy użyciu następującego typu anonimowego.

<xsd:complexType mixed="true">  
   <xsd:sequence>  
      <xsd:any minOccurs="0" maxOccurs="unbounded" processContents="lax" />  
   </xsd:sequence>  
   <xsd:anyAttribute/>  
</xsd:complexType>  

Typy implementowania interfejsu IXmlSerializable

Typy implementujące IXmlSerializable interfejs są w pełni obsługiwane przez element DataContractSerializer. Atrybut XmlSchemaProviderAttribute powinien być zawsze stosowany do tych typów w celu kontrolowania ich schematu.

Istnieją trzy odmiany typów, które implementują IXmlSerializable: typy reprezentujące dowolną zawartość, typy reprezentujące pojedynczy element i starsze DataSet typy.

  • Typy zawartości używają metody dostawcy schematu XmlSchemaProviderAttribute określonej przez atrybut . Metoda nie zwraca nullwartości , a IsAny właściwość atrybutu pozostaje w wartości domyślnej false. Jest to najbardziej typowe użycie IXmlSerializable typów.

  • Typy elementów są używane, gdy typ musi kontrolować własną IXmlSerializable nazwę elementu głównego. Aby oznaczyć typ jako typ elementu, ustaw IsAny właściwość atrybutu XmlSchemaProviderAttribute na true wartość lub zwraca wartość null z metody dostawcy schematu. Posiadanie metody dostawcy schematu jest opcjonalne dla typów elementów — można określić wartość null zamiast nazwy metody w pliku XmlSchemaProviderAttribute. Jeśli IsAny jednak określono true metodę dostawcy schematu, metoda musi zwracać wartość null.

  • Starsze DataSet typy to IXmlSerializable typy, które nie są oznaczone atrybutem XmlSchemaProviderAttribute . Zamiast tego polegają na metodzie generowania GetSchema schematu. Ten wzorzec jest używany dla DataSet typu i jego typizowanego zestawu danych pochodzi z klasy we wcześniejszych wersjach programu .NET Framework, ale jest teraz przestarzały i jest obsługiwany tylko ze starszych powodów. Nie należy polegać na tym wzorcu i zawsze stosować XmlSchemaProviderAttribute do typów IXmlSerializable .

Typy zawartości IXmlSerializable

Podczas serializacji elementu członkowskiego danych typu, który implementuje IXmlSerializable i jest typem zawartości zgodnie z definicją wcześniej, serializator zapisuje element otoki dla elementu członkowskiego danych i przekazuje kontrolkę WriteXml do metody . Implementacja WriteXml może napisać dowolny kod XML, w tym dodać atrybuty do elementu otoki. Po WriteXml zakończeniu serializator zamyka element.

W przypadku deserializacji elementu członkowskiego danych typu implementującego IXmlSerializable i jest typem zawartości zdefiniowanym wcześniej, deserializator umieszcza czytnik XML w elemencie otoki elementu elementu danych i przekazuje kontrolę do ReadXml metody. Metoda musi odczytać cały element, w tym tagi początkowe i końcowe. Upewnij się, że ReadXml kod obsługuje przypadek, w którym element jest pusty. ReadXml Ponadto implementacja nie powinna polegać na elemplecie otoki, który jest nazwany w określony sposób. Nazwa jest wybierana przez serializator może się różnić.

Dozwolone jest przypisywanie IXmlSerializable typów zawartości polimorficznie, na przykład do składowych danych typu Object. Dozwolone jest również, aby wystąpienia typu mogły mieć wartość null. Na koniec można używać IXmlSerializable typów z włączonym zachowywaniem grafu obiektów i parametrem NetDataContractSerializer. Wszystkie te funkcje wymagają serializatora WCF dołączania niektórych atrybutów do elementu otoki ("nil" i "type" w przestrzeni nazw wystąpienia schematu XML i "Id", "Ref", "Type" i "Assembly" w przestrzeni nazw specyficznej dla programu WCF).

Atrybuty do ignorowania podczas implementowania readxml

Przed przekazaniem kontrolki do ReadXml kodu deserializator sprawdza element XML, wykrywa te specjalne atrybuty XML i działa na nich. Jeśli na przykład wartość "nil" to true, wartość null jest deserializowana i ReadXml nie jest wywoływana. W przypadku wykrycia polimorfizmu zawartość elementu jest deserializowana tak, jakby była innym typem. Wywoływana jest implementacja typu przypisanego ReadXml polimorficznie. W każdym razie implementacja ReadXml powinna ignorować te atrybuty specjalne, ponieważ są obsługiwane przez deserializator.

Zagadnienia dotyczące schematu typów zawartości IXmlSerializable

Podczas eksportowania schematu IXmlSerializable typ zawartości wywoływana jest metoda dostawcy schematu. Element XmlSchemaSet jest przekazywany do metody dostawcy schematu. Metoda może dodać dowolny prawidłowy schemat do zestawu schematów. Zestaw schematów zawiera schemat, który jest już znany w czasie eksportowania schematu. Gdy metoda dostawcy schematu musi dodać element do zestawu schematów, musi określić, czy element XmlSchema z odpowiednią przestrzenią nazw już istnieje w zestawie. Jeśli tak, metoda dostawcy schematu musi dodać nowy element do istniejącego XmlSchemaelementu . W przeciwnym razie musi utworzyć nowe XmlSchema wystąpienie. Jest to ważne, jeśli są używane tablice IXmlSerializable typów. Jeśli na przykład masz IXmlSerializable typ, który zostanie wyeksportowany jako typ "A" w przestrzeni nazw "B", możliwe, że w czasie, gdy metoda dostawcy schematu jest nazywana zestawem schematów, zawiera już schemat "B" do przechowywania typu "ArrayOfA".

Oprócz dodawania typów do klasy metoda dostawcy schematu XmlSchemaSetdla typów zawartości musi zwracać wartość inną niż null. Może zwrócić element XmlQualifiedName , który określa nazwę typu schematu, który ma być używany dla danego IXmlSerializable typu. Ta kwalifikowana nazwa służy również jako nazwa kontraktu danych i przestrzeń nazw dla typu. Dozwolone jest zwracanie typu, który nie istnieje w zestawie schematów natychmiast po powrocie metody dostawcy schematu. Oczekuje się jednak, że do czasu eksportowania wszystkich powiązanych typów ( Export metoda jest wywoływana dla wszystkich odpowiednich typów w XsdDataContractExporter obiekcie i Schemas dostęp do właściwości), typ istnieje w zestawie schematów. Uzyskanie dostępu do właściwości przed wykonaniem Schemas wszystkich odpowiednich Export wywołań może spowodować wystąpienie obiektu XmlSchemaException. Aby uzyskać więcej informacji na temat procesu eksportowania, zobacz Eksportowanie schematów z klas.

Metoda dostawcy schematu może również zwrócić XmlSchemaType wartość , która ma być używana. Typ może być anonimowy lub nie. Jeśli jest anonimowy, schemat typu IXmlSerializable jest eksportowany jako typ anonimowy za każdym razem, gdy IXmlSerializable typ jest używany jako element członkowski danych. Typ IXmlSerializable nadal ma nazwę kontraktu danych i przestrzeń nazw. (Jest to określane zgodnie z opisem w temacie Nazwy kontraktów danych z wyjątkiem tego, że DataContractAttribute atrybut nie może być używany do dostosowywania nazwy. Jeśli nie jest anonimowy, musi być jednym z typów w pliku XmlSchemaSet. Ten przypadek jest odpowiednikiem zwracania XmlQualifiedName typu .

Ponadto dla typu jest eksportowana deklaracja elementu globalnego. Jeśli typ nie ma zastosowanego atrybutu XmlRootAttribute , element ma taką samą nazwę i przestrzeń nazw jak kontrakt danych, a jego właściwość "nillable" to true. Jedynym wyjątkiem jest przestrzeń nazw schematu (http://www.w3.org/2001/XMLSchema); jeśli kontrakt danych typu znajduje się w tej przestrzeni nazw, odpowiedni element globalny znajduje się w pustej przestrzeni nazw, ponieważ zabronione jest dodawanie nowych elementów do przestrzeni nazw schematu. Jeśli typ ma zastosowany atrybut, deklaracja elementu globalnego XmlRootAttribute jest eksportowana przy użyciu następujących właściwości: ElementName, Namespacei IsNullable. Wartości domyślne XmlRootAttribute zastosowane to nazwa kontraktu danych, pusta przestrzeń nazw i wartość "nillable" jest prawdziwa.

Te same reguły deklaracji elementów globalnych mają zastosowanie do starszych typów zestawów danych. Należy pamiętać, że XmlRootAttribute nie można zastąpić deklaracji elementów globalnych dodanych za pomocą kodu niestandardowego, dodanego do XmlSchemaSet metody przy użyciu dostawcy schematu lub dla GetSchema starszych typów zestawów danych.

Typy elementów IXmlSerializable

IXmlSerializable typy elementów mają właściwość ustawioną IsAny na true lub mają zwracaną metodę nulldostawcy schematu .

Serializowanie i deserializacji typu elementu jest bardzo podobne do serializacji i deserializacji typu zawartości. Istnieją jednak pewne istotne różnice:

  • Oczekuje się, że implementacja WriteXml napisze dokładnie jeden element (który może oczywiście zawierać wiele elementów podrzędnych). Nie należy pisać atrybutów poza tym pojedynczym elementem, wieloma elementami równorzędnymi ani mieszaną zawartością. Element może być pusty.

  • Implementacja ReadXml nie powinna odczytywać elementu otoki. Oczekuje się, że odczytuje jeden element, który WriteXml generuje.

  • W przypadku regularnego serializacji typu elementu (na przykład jako elementu członkowskiego danych w kontrakcie danych) serializator generuje element otoki przed wywołaniem WriteXmlelementu , tak jak w przypadku typów zawartości. Jednak podczas serializacji typu elementu na najwyższym poziomie serializator zwykle nie generuje elementu otoki w ogóle wokół elementu, który WriteXml zapisuje, chyba że główna nazwa i przestrzeń nazw zostały jawnie określone podczas konstruowania serializatora w DataContractSerializer konstruktorach lub NetDataContractSerializer . Aby uzyskać więcej informacji, zobacz Serializacja i Deserializacja.

  • Podczas serializacji typu elementu na najwyższym poziomie bez określania nazwy głównej i przestrzeni nazw w czasie budowy i WriteEndObject zasadniczo nie wykonuje żadnych operacji i WriteObjectContent wywołuje metodę WriteXml. WriteStartObject W tym trybie obiekt, który jest serializowany, nie może mieć wartości null i nie może być przypisany polimorficznie. Ponadto nie można włączyć zachowywania grafu obiektów i NetDataContractSerializer nie można go użyć.

  • Podczas deserializacji typu elementu na najwyższym poziomie bez określania nazwy głównej i przestrzeni nazw w czasie budowy zwraca true wartość , IsStartObject jeśli może znaleźć początek dowolnego elementu. ReadObject z parametrem ustawionym verifyObjectName na true zachowanie w taki sam sposób jak IsStartObject przed faktycznym odczytaniem obiektu. ReadObject następnie przekazuje kontrolę do ReadXml metody.

Schemat wyeksportowany dla typów elementów jest taki sam jak dla XmlElement typu opisanego we wcześniejszej sekcji, z tą różnicą, że metoda dostawcy schematu może dodać dowolny dodatkowy schemat do XmlSchemaSet typu zawartości. Używanie atrybutu XmlRootAttribute z typami elementów jest niedozwolone, a deklaracje elementów globalnych nigdy nie są emitowane dla tych typów.

Różnice w kodzie XmlSerializer

Interfejs IXmlSerializable i XmlSchemaProviderAttribute atrybuty są XmlRootAttribute również zrozumiałe przez XmlSerializer element . Istnieją jednak pewne różnice w sposobie ich traktowania w modelu kontraktu danych. Ważne różnice zostały podsumowane w następujących kwestiach:

  • Metoda dostawcy schematu musi być publiczna, aby można było jej używać w XmlSerializerobiekcie , ale nie musi być publiczna, aby można było jej używać w modelu kontraktu danych.

  • Metoda dostawcy schematu jest wywoływana, gdy IsAny ma wartość true w modelu kontraktu danych, ale nie w przypadku elementu XmlSerializer.

  • XmlRootAttribute Jeśli atrybut nie jest obecny dla zawartości lub starszych typów zestawów danych, XmlSerializer eksportuje deklarację elementu globalnego w pustej przestrzeni nazw. W modelu kontraktu danych używana przestrzeń nazw jest zwykle przestrzenią nazw kontraktu danych zgodnie z wcześniejszym opisem.

Należy pamiętać o tych różnicach podczas tworzenia typów, które są używane z obu technologii serializacji.

Importowanie schematu IXmlSerializable

Podczas importowania schematu wygenerowanego na podstawie IXmlSerializable typów istnieje kilka możliwości:

  • Wygenerowany schemat może być prawidłowym schematem kontraktu danych, zgodnie z opisem w temacie Data Contract Schema Reference (Dokumentacja schematu kontraktu danych). W takim przypadku schemat można zaimportować jak zwykle, a zwykłe typy kontraktów danych są generowane.

  • Wygenerowany schemat może nie być prawidłowym schematem kontraktu danych. Na przykład metoda dostawcy schematu może generować schemat obejmujący atrybuty XML, które nie są obsługiwane w modelu kontraktu danych. W takim przypadku można zaimportować schemat jako IXmlSerializable typy. Ten tryb importowania nie jest domyślnie włączony, ale można go łatwo włączyć — na przykład za pomocą /importXmlTypes przełącznika wiersza polecenia do narzędzia ServiceModel Metadata Tool (Svcutil.exe). Opisano to szczegółowo w temacie Importing Schema to Generate Classes (Importowanie schematu do generowania klas). Należy pamiętać, że musisz pracować bezpośrednio z kodem XML dla wystąpień typu. Możesz również rozważyć użycie innej technologii serializacji, która obsługuje szerszy zakres schematów — zobacz temat dotyczący korzystania z programu XmlSerializer.

  • Możesz chcieć ponownie użyć istniejących IXmlSerializable typów na serwerze proxy zamiast generować nowe. W tym przypadku można użyć funkcji typów, do których odwołuje się odwołanie opisane w temacie Importowanie schematu do generowania typów, aby wskazać typ do ponownego użycia. Odpowiada to użyciu przełącznika /reference svcutil.exe, który określa zestaw zawierający typy do ponownego użycia.

Reprezentowanie dowolnego kodu XML w kontraktach danych

Tablica XmlElementtypów XmlNode i IXmlSerializable umożliwia wstrzyknięcie dowolnego kodu XML do modelu kontraktu danych. Element DataContractSerializer i NetDataContractSerializer przekaż tę zawartość XML do używanego składnika zapisywania XML bez zakłócania procesu. Jednak zapisy XML mogą wymuszać pewne ograniczenia dotyczące kodu XML, które zapisują. Oto kilka ważnych przykładów:

  • Zapisy XML zwykle nie zezwalają na deklarację dokumentu XML (na przykład <?xml version='1.0')> w środku pisania innego dokumentu. Nie można pobrać pełnego dokumentu XML i serializować go jako Array elementu XmlNode członkowskiego danych. W tym celu należy usunąć deklarację dokumentu lub użyć własnego schematu kodowania, aby go przedstawić.

  • Wszystkie składniki zapisywania XML dostarczane z usługą WCF odrzucają instrukcje przetwarzania XML (<? ... ?>) i definicje typów dokumentów (<! ... >), ponieważ nie są dozwolone w komunikatach PROTOKOŁU SOAP. Ponownie możesz użyć własnego mechanizmu kodowania, aby obejść to ograniczenie. Jeśli musisz uwzględnić te elementy w wynikowym kodzie XML, możesz napisać koder niestandardowy, który używa składników zapisywania XML, które je obsługują.

  • Podczas implementowania WriteXmlmetody unikaj wywoływania WriteRaw metody w składniku zapisywania XML. WCF używa różnych kodowań XML (w tym binarnych), jest bardzo trudne lub niemożliwe do użycia WriteRaw , tak aby wynik był używany w dowolnym kodowaniu.

  • Podczas implementowania WriteXmlprogramu unikaj używania WriteEntityRef metod i WriteNmToken , które nie są obsługiwane w składnikach zapisywania XML dostarczanych z usługą WCF.

Używanie zestawu danych, typizowanego zestawu danych i tabeli DataTable

Korzystanie z tych typów jest w pełni obsługiwane w modelu kontraktu danych. W przypadku korzystania z tych typów należy wziąć pod uwagę następujące kwestie:

  • Schemat dla tych typów (szczególnie DataSet z typowymi klasami pochodnymi) może nie być współdziałalny z niektórymi platformami innych niż WCF lub może spowodować niską użyteczność w przypadku użycia z tymi platformami. Ponadto użycie DataSet typu może mieć wpływ na wydajność. Na koniec może to utrudnić przechowywanie wersji aplikacji w przyszłości. Rozważ użycie jawnie zdefiniowanych typów kontraktów DataSet danych zamiast typów kontraktów.

  • Podczas importowania DataSet lub DataTable tworzenia schematu należy odwołać się do tych typów. Za pomocą narzędzia wiersza polecenia Svcutil.exe można to zrobić, przekazując System.Data.dll nazwę zestawu do przełącznika /reference . W przypadku importowania schematu typizowanego zestawu danych należy odwołać się do typu wpisanego zestawu danych. W przypadku Svcutil.exe przekaż lokalizację zestawu typizowanego zestawu zestawu do przełącznika /reference . Aby uzyskać więcej informacji na temat odwoływania się do typów, zobacz Importowanie schematu do generowania klas.

Obsługa typowanych zestawów danych w modelu kontraktu danych jest ograniczona. Typowane zestawy danych można serializować i deserializować i eksportować ich schemat. Jednak importowanie schematu kontraktu danych nie może wygenerować nowych typów typu DataSet ze schematu, ponieważ może ponownie używać istniejących. Możesz wskazać istniejący typowy zestaw danych przy użyciu przełącznika /r Svcutil.exe. Jeśli spróbujesz użyć Svcutil.exe bez /r przełącznika usługi korzystającej z typowanego zestawu danych, zostanie automatycznie wybrany alternatywny serializator (XmlSerializer). Jeśli musisz użyć elementu DataContractSerializer i musisz wygenerować zestawy danych na podstawie schematu, możesz użyć następującej procedury: wygenerować typ typu Zestaw danych (przy użyciu narzędzia Xsd.exe z /d przełącznikiem usługi), skompilować typy, a następnie wskazać je przy użyciu /r przełącznika Svcutil.exe.

Zobacz też