データ コントラクトの XML および ADO.NET の種類
Windows Communication Foundation (WCF) データ コントラクト モデルでは、XML を直接表現する特定の型がサポートされています。 シリアライザーは、これらの型を XML にシリアル化するとき、型の XML コンテンツを書き出しますが、それ以上の処理は行いません。 サポートされている型は、XmlElement、XmlNode の配列 (XmlNode
型自体はサポートされていません)、および IXmlSerializable を実装した型です。 データベース プログラミングでは、DataSet 型、DataTable 型、および型指定されたデータセットが一般的に使用されます。 これらの型は IXmlSerializable
インターフェイスを実装するので、データ コントラクト モデルでシリアル化可能です。 この型に関する考慮事項について、このトピックの最後に説明します。
XML 型
XmlElement
XmlElement
型は、その XML コンテンツを使用してシリアル化されます。 たとえば、次の型を使用するとします。
[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
これは、次のように XML にシリアル化されます。
<MyDataContract xmlns="http://schemas.contoso.com">
<myDataMember>
<myElement xmlns="" myAttribute="myValue">
myContents
</myElement>
</myDataMember>
</MyDataContract>
ラッパー データ メンバー要素 <myDataMember>
が引き続き存在している点に注意してください。 データ コントラクト モデルにはこの要素を削除する方法がありません。 このモデルを処理するシリアライザー (DataContractSerializer と NetDataContractSerializer) では、このラッパー要素に特別な属性が出力されることがあります。 この特別な属性には、標準の XML スキーマ インスタンスの "nil" 属性 (XmlElement
を null
に設定できるようにする属性) や "type" 属性 (XmlElement
をポリモーフィックに使用できるようにする属性) などがあります。 また、"Id"、"Ref"、"Type"、および "Assembly" は、WCF に固有の XML 属性です。 これらの属性が出力されるのは、オブジェクト グラフの保存モードを有効にするか XmlElement
を使用する場合に NetDataContractSerializer をサポートするためです (オブジェクト グラフの保存モードの詳細については、「シリアル化と逆シリアル化」を参照してください)。
XmlElement
の配列またはコレクションを使用できます。これらは、他の配列またはコレクションとして処理されます。 つまり、コレクション全体のラッパー要素と、配列に含まれる <myDataMember>
ごとに個別のラッパー要素 (上記の例の XmlElement
と同様) が存在することになります。
逆シリアル化時には、デシリアライザーによって受信 XML から XmlElement
が作成されます。 有効な親 XmlDocument は、デシリアライザーによって提供されます。
XmlElement
に逆シリアル化される XML フラグメントでは、先祖要素のプレフィックス定義に依存するのではなく、使用するすべてのプレフィックスを定義しておく必要があります。 これは、DataContractSerializer
を使用して、DataContractSerializer
以外の別のソースから XML にアクセスする場合にのみ考慮する必要があります。
DataContractSerializer
で使用する場合は、XmlElement
をポリモーフィックに割り当てることができますが、その対象は Object 型のデータ メンバーのみです。 IEnumerable が実装されていても、XmlElement
をコレクション型として使用したり、IEnumerable データ メンバーに割り当てることはできません。 すべてのポリモーフィックな割り当てと同様に、DataContractSerializer
によって、生成される XML にデータ コントラクト名が出力されます。 この場合、これは http://schemas.datacontract.org/2004/07/System.Xml
名前空間の "XmlElement" です。
NetDataContractSerializer
を使用する場合、XmlElement
の有効なポリモーフィック割り当て (Object
または IEnumerable
への割り当て) がすべてサポートされます。
XmlElement
から派生した型がポリモーフィックに割り当てられているかどうかに関係なく、このような型と上記の 2 つのシリアライザーを一緒に使用しないでください。
XmlNode の配列
XmlNode の配列の使用は、XmlElement
の使用に非常に似ています。 XmlNode
の配列を使用すると、XmlElement
を使用する場合よりも高い柔軟性が得られます。 たとえば、データ メンバーがラップする要素内に複数の要素を作成できます。 データ メンバーがラップする要素内には、XML コメントなどの要素以外のコンテンツを挿入することもできます。 さらに、ラップする側のデータ メンバー要素にも属性を挿入できます。 これらはすべて、XmlNode
の配列に XmlNode
の特定の派生クラス (XmlAttribute、XmlElement
、XmlComment など) を追加することによって実現できます。 たとえば、次の型を使用するとします。
[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
シリアル化すると、生成される XML は次のコードのようになります。
<MyDataContract xmlns="http://schemas.contoso.com">
<myDataMember myAttribute="myValue">
<!--myComment-->
<myElement xmlns="" myAttribute="myValue">
myContents
</myElement>
<myElement xmlns="" myAttribute="myValue">
myContents
</myElement>
</myDataMember>
</MyDataContract>
データ メンバー ラッパー要素 <myDataMember>
には、1 つの属性、1 つのコメント、および 2 つの要素が含まれています。 これらが、シリアル化された 4 つの XmlNode
インスタンスです。
結果的に無効な XML になる XmlNode
の配列は、シリアル化できません。 たとえば、最初のインスタンスが XmlNode
で、次のインスタンスが XmlElement
という 2 つの XmlAttribute インスタンスの配列は、無効です。このシーケンスは、有効な XML インスタンスに対応していません (属性を関連付ける場所がありません)。
XmlNode
の配列の逆シリアル化時には、ノードが作成され、そのノードに受信 XML からの情報が追加されます。 有効な親 XmlDocument は、デシリアライザーによって提供されます。 ラッパー データ メンバー要素にあるすべての属性を含めて、すべてのノードが逆シリアル化されます。ただし、WCF シリアライザーによってその要素に配置される属性 (ポリモーフィック割り当てを示すための属性など) を除きます。 XML フラグメントですべての名前空間プレフィックスを定義するときの注意点は、XmlNode
の逆シリアル化に適用されるのと同様に、XmlElement
の配列の逆シリアル化にも適用されます。
オブジェクト グラフの保存を有効にしてシリアライザーを使用した場合、オブジェクトの等価性は、個別の XmlNode
インスタンスではなく、XmlNode
配列のレベルでのみ保存されます。
1 つ以上のノードが XmlNode
に設定された null
の配列をシリアル化しないようにしてください。 配列メンバー全体を null
にすることはできますが、配列に格納された個々の XmlNode
を null にすることはできません。 配列メンバー全体が null の場合、ラッパー データ メンバー要素には、配列メンバー全体が null であることを示す特別な属性が含まれます。 逆シリアル化時にも、配列メンバー全体が null になります。
XmlNode
の正規の配列だけが、シリアライザーによって特別に処理されます。 XmlNode
を含む他のコレクション型として宣言されたデータ メンバーや、XmlNode
から派生した型の配列として宣言されたデータ メンバーには、特別な処理は行われません。 このため、これらのデータ メンバーは、シリアル化に関するその他の条件のいずれかを満たしている場合を除き、通常はシリアル化できません。
XmlNode
の配列の配列またはコレクションを使用できます。 コレクション全体のラッパー要素と、外側の配列またはコレクションに含まれる <myDataMember>
の配列ごとに個別のラッパー要素 (上記の例の XmlNode
と同様) が存在することになります。
Array の Object
または Array
の IEnumerable
型のデータ メンバーに XmlNode
インスタンスを追加しても、そのデータ メンバーが Array
インスタンスの XmlNode
として扱われることはありません。 配列の各メンバーは個別にシリアル化されます。
DataContractSerializer
を使用する場合、XmlNode
の配列をポリモーフィックに割り当てることができますが、その対象は Object
型のデータ メンバーだけです。 IEnumerable
が実装されていても、XmlNode
の配列をコレクション型として使用したり、IEnumerable
データ メンバーに割り当てることはできません。 すべてのポリモーフィックな割り当てと同様に、DataContractSerializer
によって、生成される XML にデータ コントラクト名が出力されます。この場合、これは http://schemas.datacontract.org/2004/07/System.Xml
名前空間の "ArrayOfXmlNode" です。 NetDataContractSerializer
を使用する場合は、XmlNode
配列の有効な割り当てがサポートされます。
スキーマの考慮事項
XML 型のスキーマ マッピングの詳細については、「データ コントラクト スキーマの参照」を参照してください。 ここでは、重要な点の概要について説明します。
XmlElement
型のデータ メンバーは、次の匿名型を使用して定義された要素にマップされます。
<xsd:complexType>
<xsd:sequence>
<xsd:any minOccurs="0" processContents="lax" />
</xsd:sequence>
</xsd:complexType>
XmlNode
の Array 型のデータ メンバーは、次の匿名型を使用して定義された要素にマップされます。
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:any minOccurs="0" maxOccurs="unbounded" processContents="lax" />
</xsd:sequence>
<xsd:anyAttribute/>
</xsd:complexType>
IXmlSerializable インターフェイスを実装する型
IXmlSerializable
インターフェイスを実装する型は、DataContractSerializer
で完全にサポートされます。 これらの型には、スキーマを制御するために必ず XmlSchemaProviderAttribute 属性を適用する必要があります。
IXmlSerializable
を実装する型には、任意のコンテンツを表す型、1 つの要素を表す型、および従来の DataSet 型の 3 種類があります。
コンテンツ型では、
XmlSchemaProviderAttribute
属性によって指定されたスキーマ プロバイダー メソッドが使用されます。 このメソッドからnull
が返されることはなく、属性の IsAny プロパティは既定値false
のままになります。 これは、IXmlSerializable
型の最も一般的な使用方法です。要素型は、
IXmlSerializable
型が自身のルート要素名を制御する必要があるときに使用します。 型を要素型としてマークするには、IsAny 属性の XmlSchemaProviderAttribute プロパティをtrue
に設定するか、スキーマ プロバイダー メソッドから null を返します。 スキーマ プロバイダー メソッドの使用は、要素型ではオプションです。XmlSchemaProviderAttribute
でメソッド名の代わりに null を指定できます。 ただし、IsAny
がtrue
で、スキーマ プロバイダー メソッドが指定されている場合、メソッドは null を返す必要があります。従来の DataSet 型は、
IXmlSerializable
属性でマークされていないXmlSchemaProviderAttribute
型です。 これらの型は、スキーマ生成に関して GetSchema メソッドに依存しています。 以前のバージョンの .NET Framework では、このパターンがDataSet
型に使用され、型指定されたデータセットからクラスが派生されます。ただし、現在、このパターンは使用されなくなっており、従来の型に対応することだけを目的としてサポートされています。 このパターンに依存せず、必ずXmlSchemaProviderAttribute
をIXmlSerializable
型に適用してください。
IXmlSerializable コンテンツ型
IXmlSerializable
を実装しており、以前に定義したコンテンツ型である型のデータ メンバーをシリアル化すると、シリアライザーはそのデータ メンバーのラッパー要素を書き込み、WriteXml メソッドに制御を渡します。 WriteXml 実装により、ラッパー要素に属性が追加されるなど、任意の XML が書き込まれることがあります。 WriteXml
の実行後、シリアライザーは要素を閉じます。
IXmlSerializable
を実装しており、以前に定義したコンテンツ型である型のデータ メンバーを逆シリアル化すると、デシリアライザーはそのデータ メンバーのラッパー要素に XML リーダーを配置し、ReadXml メソッドに制御を渡します。 このメソッドは、開始タグと終了タグを含む、要素全体を読み取る必要があります。 ReadXml
コードでは、要素が空の場合も忘れずに処理してください。 また、ReadXml
の実装では、特定の方法で名前が付けられたラッパー要素に依存しないようにしてください。 シリアライザーによって選択される名前は、異なる場合があります。
IXmlSerializable
コンテンツ型は、たとえば Object 型のデータ メンバーなどに、ポリモーフィックに割り当てることができます。 また、型インスタンスを null にすることもできます。 さらに、IXmlSerializable
型は、オブジェクト グラフの保存を有効にして NetDataContractSerializer で使用することも可能です。 これらのすべての機能を実現するには、WCF シリアライザーが特定の属性 (XML スキーマ インスタンス名前空間の "nil" と "type"、WCF 固有の名前空間の "Id"、"Ref"、"Type"、および "Assembly") をラッパー要素に追加する必要があります。
ReadXml を実装するときに無視する属性
ReadXml
コードに制御を渡す前に、デシリアライザーは、XML 要素を調べ、前述の特別な XML 属性を検出し、その属性に従って動作します。 たとえば、"nil" が true
の場合は、null 値が逆シリアル化され、ReadXml
は呼び出されません。 ポリモーフィズムが検出された場合は、要素のコンテンツが別の型と同様に逆シリアル化されます。 ポリモーフィックに割り当てられた型の ReadXml
実装が呼び出されます。 どの場合も、これらの特別な属性がデシリアライザーによって処理されるため、ReadXml
実装ではこれらの属性を無視する必要があります。
IXmlSerializable コンテンツ型のスキーマに関する考慮事項
IXmlSerializable
コンテンツ型のスキーマをエクスポートすると、スキーマ プロバイダー メソッドが呼び出されます。 このスキーマ プロバイダー メソッドには、XmlSchemaSet が渡されます。 このメソッドは、有効なスキーマをスキーマ セットに追加できます。 スキーマ セットには、スキーマをエクスポートした時点で既に認識されていたスキーマが格納されます。 スキーマ プロバイダー メソッドは、スキーマ セットに項目を追加する必要があるときに、適切な名前空間を持つ XmlSchema がそのセットに既に存在するかどうかを確認する必要があります。 存在する場合、スキーマ プロバイダー メソッドは新しい項目を既存の XmlSchema
に追加する必要があります。 存在しない場合、新しい XmlSchema
インスタンスを作成する必要があります。 これは、IXmlSerializable
型の配列を使用する場合に重要です。 たとえば、IXmlSerializable
型を名前空間 "B" の "A" 型としてエクスポートする場合、スキーマ プロバイダー メソッドが呼び出される前に、"B" が "ArrayOfA" 型を保持するためのスキーマがスキーマ セットに既に存在している可能性があります。
型を XmlSchemaSet に追加する以外に、コンテンツ型のスキーマ プロバイダー メソッドは null 以外の値を返す必要があります。 このメソッドは、特定の XmlQualifiedName 型で使用するスキーマ型の名前を指定する IXmlSerializable
を返すことができます。 この修飾名は、その型のデータ コントラクト名および名前空間としても使用されます。 スキーマ プロバイダー メソッドは、スキーマ セットにまだ存在していない型であっても、復帰時に返すことができます。 ただし、関連するすべての型がエクスポートされる (Export の関連するすべての型に対して XsdDataContractExporter メソッドが呼び出され、Schemas プロパティにアクセスする) までに、その型がスキーマ セットに存在している必要があります。 関連するすべての Schemas
呼び出しが実行される前に Export
プロパティにアクセスすると、XmlSchemaException が発生する可能性があります。 エクスポート プロセスの詳細については、「クラスからのスキーマのエクスポート」を参照してください。
スキーマ プロバイダー メソッドは、使用する XmlSchemaType を返すこともできます。 その型は、匿名の場合とそうでない場合があります。 匿名の場合、IXmlSerializable
型のスキーマは、IXmlSerializable
型がデータ メンバーとして使用されるたびに匿名型としてエクスポートされます。 IXmlSerializable
型には、データ コントラクト名と名前空間が引き続き保持されます (これは、「データ コントラクト名」で説明されているとおりに決定されます。ただし、DataContractAttribute 属性を使用して名前をカスタマイズすることはできません)。匿名でない場合は、XmlSchemaSet
に含まれる型のいずれかである必要があります。 これは、型の XmlQualifiedName
を返す場合と同じです。
さらに、型のグローバル要素宣言がエクスポートされます。 型に XmlRootAttribute 属性が適用されていない場合、その要素にはデータ コントラクトと同じ名前と名前空間が使用され、その "nillable" プロパティは true
に設定されます。 唯一の例外は、スキーマ名前空間 (http://www.w3.org/2001/XMLSchema
) です。型のデータ コントラクトがこの名前空間にある場合は、新しい要素をスキーマ名前空間に追加することが禁止されているため、対応するグローバル要素は、空白の名前空間に属することになります。 型に XmlRootAttribute
属性が適用されている場合、グローバル要素宣言は、次の ElementName、Namespace、IsNullable の各プロパティを使用してエクスポートされます。 XmlRootAttribute
が適用された場合の既定値は、データ コントラクト名、空白の名前空間、および true に設定された "nillable" です。
同じグローバル要素宣言の規則が、従来のデータセット型に適用されます。 XmlRootAttribute
は、カスタム コードによって追加されたグローバル要素宣言をオーバーライドできません。これには、スキーマ プロバイダー メソッドを使用して XmlSchemaSet
に追加された場合と、従来のデータセット型に対して GetSchema
を使用して追加された場合があります。
IXmlSerializable 要素型
IXmlSerializable
要素型には、IsAny
に設定された true
プロパティか、null
を返すスキーマ プロバイダー メソッドのいずれかが含まれています。
要素型のシリアル化と逆シリアル化は、コンテンツ型のシリアル化と逆シリアル化に非常に似ています。 ただし、重要な違いがいくつかあります。
WriteXml
の実装では、要素 (これには複数の子要素が含まれている可能性もありますが) を 1 つだけ出力することが想定されています。 この 1 つの要素の外側にある属性、複数の兄弟要素、またはこれらが混在したコンテンツを出力することはできません。 要素は空であってもかまいません。ReadXml
の実装では、ラッパー要素の読み取りは想定されていません。 読み取ることが想定されているのは、WriteXml
で生成される要素 1 つのみです。要素型を一様にシリアル化する場合 (データ コントラクトのデータ メンバーとしてシリアル化する場合など) は、コンテンツ型の場合と同様に、
WriteXml
を呼び出す前にラッパー要素が出力されます。 ただし、WriteXml
コンストラクターまたはDataContractSerializer
コンストラクターによるシリアライザーの構築時にルート名と名前空間が明示的に指定されていない限り、トップ レベルで要素型をシリアル化しても、通常はNetDataContractSerializer
で書き出される要素を囲むラッパー要素が出力されることはありません。 詳細については、「シリアル化と逆シリアル化」を参照してください。構築時にルート名と名前空間を指定せずにトップ レベルで要素型をシリアル化した場合、WriteStartObject と WriteEndObject では基本的に何も実行されず、WriteObjectContent によって
WriteXml
が呼び出されます。 このモードでは、シリアル化されるオブジェクトは null にできず、ポリモーフィックに割り当てることができません。 また、オブジェクト グラフの保存を有効化できず、NetDataContractSerializer
も使用できません。構築時にルート名と名前空間を指定せずにトップ レベルで要素型を逆シリアル化したときに、要素の先頭を検出できた場合は、IsStartObject が
true
を返します。 ReadObject パラメーターがverifyObjectName
に設定されているtrue
は、実際にオブジェクトを読み取る前の動作がIsStartObject
と同様です。 その後、ReadObject
は制御をReadXml
メソッドに渡します。
要素型の場合も、エクスポートされるスキーマは、前のセクションで説明した XmlElement
型に対するスキーマと同じです。ただし、スキーマ プロバイダー メソッドは、コンテンツ型と同様、追加のスキーマを XmlSchemaSet に追加できます。 要素型には XmlRootAttribute
属性を使用することはできないので、グローバル要素宣言は要素型に対して出力されません。
XmlSerializer との相違点
IXmlSerializable
インターフェイス、XmlSchemaProviderAttribute
属性、および XmlRootAttribute
属性は、XmlSerializer でも認識されます。 ただし、データ コントラクト モデルでの処理方法に違いがあります。 重要な違いを以下にまとめます。
スキーマ プロバイダー メソッドは、
XmlSerializer
で使用できるようにするためにパブリックにする必要がありますが、データ コントラクト モデルで使用するためにパブリックにする必要はありません。スキーマ プロバイダー メソッドは、データ コントラクト モデルで
IsAny
が true の場合に呼び出されますが、XmlSerializer
では呼び出されません。コンテンツ型または従来のデータセット型に
XmlRootAttribute
属性がない場合、XmlSerializer
は、グローバル要素宣言を空白の名前空間にエクスポートします。 データ コントラクト モデルで通常使用される名前空間は、前に説明したとおりデータ コントラクトの名前空間です。
両方のシリアル化技術で使用する型を作成する場合には、これらの違いに注意してください。
IXmlSerializable スキーマのインポート
IXmlSerializable
型から生成されたスキーマをインポートする場合、次のような状況が考えられます。
生成されるスキーマは、「データ コントラクト スキーマの参照」で説明されているように、有効なデータ コントラクト スキーマである場合があります。 この場合は、スキーマを通常どおりにインポートでき、通常のデータ コントラクト型が生成されます。
生成されたスキーマが、有効なデータ コントラクト スキーマではない場合があります。 たとえば、スキーマ プロバイダー メソッドによって、データ コントラクト モデルでサポートされていない XML 属性を含むスキーマが生成されることがあります。 この場合、スキーマを
IXmlSerializable
型としてインポートできます。 このインポート モードは、既定では有効になっていませんが、たとえば ServiceModel メタデータ ユーティリティ ツール (Svcutil.exe) で/importXmlTypes
コマンド ライン スイッチを使用して、簡単に有効にすることができます。 これについての詳細は、「クラスを生成するためのスキーマのインポート」で説明しています。 型インスタンスを処理するには、XML を直接操作する必要があります。XmlSerializer
の使用方法に関するトピックを参照し、より広い範囲のスキーマをサポートする別のシリアル化技術を使用することを検討することもできます。新しい型を生成する代わりに、プロキシ内の既存の
IXmlSerializable
型を再利用できます。 この場合、「型を作成するためのスキーマのインポート」で説明する参照型の機能を使用して、再利用する型を示すことができます。 これは、Svcutil.exe で/reference
スイッチを使用して、再利用する型を含むアセンブリを指定することに相当します。
データ コントラクトでの任意の XML の表現
XmlElement
型、XmlNode
の配列、および IXmlSerializable
型を使用すると、任意の XML をデータ コントラクト モデルに挿入できます。 DataContractSerializer
と NetDataContractSerializer
は、プロセスには介入せずに、使用している XML ライターにこの XML コンテンツを渡します。 ただし、XML ライターは、出力する XML に対して特定の制限を適用することがあります。 次に重要な例を具体的に示します。
通常、XML ライターでは、別のドキュメントの書き込み中の XML ドキュメントの宣言 (例: <?xml version=’1.0’ ?>) は許可されません。 完全な XML ドキュメントを取得して、それを
Array
データ メンバーのXmlNode
としてシリアル化したりすることはできません。 これを実行するには、ドキュメントの宣言を取り除くか、独自のエンコード方法でこの宣言を表現する必要があります。XML 処理命令 (<? … ?>) と文書型定義 (<! … >) は、SOAP メッセージで使用できないため、WCF で提供されるすべての XML ライターで拒否されます。 この場合も、独自のエンコード機構を使用して、この制限に対処できます。 生成される XML に XML 処理命令と文書型定義を含める必要がある場合は、この 2 つをサポートする XML ライターを使用するカスタム エンコーダーを作成できます。
WriteXml
を実装するときは、XML ライターで WriteRaw メソッドを呼び出さないようにします。 WCF では、バイナリを含むさまざまな XML エンコードを使用します。その結果をどのエンコードでも使用できるようにWriteRaw
を使用することは、非常に困難または不可能です。WriteXml
を実装するときは、WCF で提供される XML ライターでサポートされていない WriteEntityRef メソッドと WriteNmToken メソッドを使用しないようにしてください。
DataSet、Typed DataSet、および DataTable の使用
データ コントラクト モデルでは、この 3 つの型の使用が完全にサポートされています。 これらの型を使用する場合は、次の点に注意してください。
この 3 つの型 (特に、DataSet および型指定された派生クラス) のスキーマは、WCF 以外の一部のプラットフォームと相互運用できない場合があります。また、このようなプラットフォームで使用しても、結果的に使いにくい場合もあります。 また、
DataSet
型の使用はパフォーマンスに影響を与えることがあります。 さらに、将来的にアプリケーションのバージョン管理が通常より難しくなる可能性もあります。 コントラクトでは、DataSet
型の代わりに、明示的に定義されたデータ コントラクト型を使用することを検討してください。DataSet
スキーマまたはDataTable
スキーマをインポートする際には、これらの型を参照することが重要です。 Svcutil.exe コマンド ライン ツールを使用すると、System.Data.dll アセンブリ名を/reference
スイッチに渡すことによって、この参照を実現できます。 型指定されたデータセット スキーマをインポートする場合、その型指定されたデータセットの型を参照する必要があります。 Svcutil.exe を使用して、型指定されたデータセットのアセンブリの場所を/reference
スイッチに渡します。 型の参照の詳細については、「クラスを生成するためのスキーマのインポート」を参照してください。
データ コントラクト モデルでは、型指定された DataSet のサポートが制限されています。 型指定された DataSet は、シリアル化と逆シリアル化が可能であり、スキーマをエクスポートすることもできます。 ただし、データ コントラクト スキーマのインポートでは、既存のスキーマの再利用のみが行われるため、型指定された新しい DataSet 型をスキーマから生成することはできません。 Svcutil.exe ツールで /r
スイッチを使用して、型指定された既存の DataSet を指し示すことができます。 型指定されたデータセットを使用するサービスで、/r
スイッチを指定せずに Svcutil.exe を使用しようとすると、代替のシリアライザー (XmlSerializer) が自動的に選択されます。 DataContractSerializer を使用することも、スキーマから DataSet を生成することも必要である場合は、(サービスで /d
スイッチを指定した Xsd.exe ツールを使用して) 型指定された DataSet 型を生成し、型をコンパイルした後に、Svcutil.exe で /r
スイッチを使用して、それらの型を指し示します。