DataTableの列のスキーマ (schema) を表します。
| 型 | プロパティ | 内容 | 既定値 |
|---|---|---|---|
| DataTable | Table | 列が属しているDataTable | |
| string | ColumnName | 列の名前。これが既定の空文字列のままDataColumnCollectionに追加されると、既定の名前であるColumn1、Column2…が設定される | |
| string | Caption | 列の見出し (キャプション)。これが設定されていないならば、ColumnNameの値が返される | |
| bool | AllowDBNull | trueならば、nullを許可する | true |
| bool | Unique | trueならば、唯一でなければならない | false |
| bool | ReadOnly | trueならば、読み取り専用
Tableに追加する前に値を設定しなければならない。追加後に設定すると、ReadOnlyExceptionが投げられる。一方で追加前か除去後のDetachedの状態ならば、値を変更できる |
false |
| bool | AutoIncrement | trueならば、テーブルに行を追加したとき、またはDataTable.NewRow()で行を作成したときに、増加した値を自動的に設定する | false |
| Type | DataType | 列に格納されるデータの型。これはDataView.SortやDataView.RowFilterの基準となる | String |
| object | DefaultValue | 新しい行を作成したときの、列の既定値 | |
| DataSetDateTime | DateTimeMode | 列のDateTimeMode | UnspecifiedLocal |
| MappingType | ColumnMapping | 列のMappingType | Element |
| string | Expression | 式。行のフィルタ、演算または集合関数の結果の列への出力に用いる | "" |
RowFilterではParentとChildを親や子テーブルを指定するための接頭辞として用いているため、これらを列の名前とすることは避けます。
DataTable table = new DataTable();
table.Columns.Add("parent");
table.Select("parent = 1"); // SyntaxErrorException「Dot が必要ですが、位置 8 の実際のトークンは BinaryOp です。」
DataTable.CaseSensitiveがfalseならば、大文字/小文字の区別なく唯一でなければなりません。つまり"a"と"A"は区別されないため、"a"がある列に"A"は追加できません。またLocaleの設定によっては、"あ"と"ア"も区別されません。
DataTable table = new DataTable();
table.CaseSensitive = false;
table.Locale = new System.Globalization.CultureInfo("ja-JP");
DataColumn column = table.Columns.Add("col1");
column.Unique = true;
table.Rows.Add("a");
table.Rows.Add("A"); // ConstraintException「列 'col1' は一意であるように制約されています。値 'A' は既に存在します。」
table.Rows.Add("あ");
table.Rows.Add("ア"); // ConstraintException「列 'col1' は一意であるように制約されています。値 'ア' は既に存在します。」
Uniqueをtrueにすると、テーブルの制約にUniqueConstraintが追加されます。一方でUniqueConstraintを追加すると、そこで指定した列のUniqueがtrueになります。
DataRowStateがDeletedとなっていれば、その行の値と重複していても追加できます。ただし追加後にその行の削除を取り消そうとするとConstraintExceptionが投げられます。
DataTable table = new DataTable();
DataColumn column = table.Columns.Add();
column.Unique = true;
DataRow row = table.Rows.Add("a");
row.AcceptChanges();
row.Delete();
DataRowState state = row.RowState; // Deleted
table.Rows.Add("a");
row.RejectChanges(); // ConstraintException
AutoIncrementをtrueとした列に値を自動的に設定させるには、値を指定しないかnullを指定します。DataColumn.AutoIncrement Property (System.Data) | Microsoft Learn
DataTable table = new DataTable(); DataColumn column = table.Columns.Add(); string type1 = column.DataType.FullName; // "System.String" column.AutoIncrement = true; string type2 = column.DataType.FullName; // "System.Int32" … trueに設定するときDataTypeがInt16、Int32、Int64以外ならば、Int32に変更される column.AutoIncrementSeed = 10; // AutoIncrementで設定するときの初期値。既定は0 column.AutoIncrementStep = 2; // AutoIncrementで加算する値。既定は1 DataRow row1 = table.Rows.Add(); // 10 … row1.ItemArray[0]の値 DataRow row2 = table.Rows.Add(); // 12 DataRow row3 = table.Rows.Add(20); // 20 … 任意の値を指定することも可能 DataRow row4 = table.Rows.Add(); // 22 … 最大値に対して加算された値になる row2.Delete(); // 途中の行を削除 DataRow row5 = table.Rows.Add(); // 24 row5.Delete(); // 末尾の行を削除。現在の最大値は22となる DataRow row6 = table.Rows.Add(); // 26 … 現在の最大値とは無関係に、これまでの最大値となる row6[column] = 30; // 現在の最大値を書き換える DataRow row7 = table.Rows.Add(); // 32 … 最大値に対して加算された値になる DataRow row8 = table.NewRow(); // 34 … NewRow()で作成した時点で値が設定される table.Rows.Add(row8);
AutoIncrementをtrueとする列のDataTypeがInt16、Int32、Int64以外ならばInt32に設定されるため、値がInt32.MaxValueを超えるとオーバーフローします。
DataTable table = new DataTable();
DataColumn column = table.Columns.Add();
column.AutoIncrement = true;
column.AutoIncrementSeed = int.MaxValue;
table.Rows.Add();
table.Rows.Add(); // OverflowException「Int32 型の値が大きすぎるか、または小さすぎます。」
下表の値を指定できます。
| 列挙子 | 値 | 列の割り当て先 |
|---|---|---|
| Element | 1 | XML要素 |
| Attribute | 2 | XML属性 |
| SimpleContent | 3 | System.Xml.XmlTextノード |
| Hidden | 4 | 内部構造 |
ColumnMappingを変更すると、
DataTable table1 = new DataTable("sample1");
table1.Columns.Add("Element").ColumnMapping = MappingType.Element;
table1.Columns.Add("Attribute").ColumnMapping = MappingType.Attribute;
//table1.Columns.Add("SimpleContent").ColumnMapping = MappingType.SimpleContent; // ArgumentException「SimpleContent 列を、要素列または入れ子にされたリレーションシップを含むテーブルには追加できません。」
table1.Columns.Add("Hidden").ColumnMapping = MappingType.Hidden;
table1.Rows.Add("ELEMENT", "ATTRIBUTE", "HIDDEN");
table1.WriteXml("sample1.xml");
table1.WriteXmlSchema("sample1.xsd");
DataTable.WriteXml()では次のように、
<?xml version="1.0" standalone="yes"?>
<DocumentElement>
<sample1 Attribute="ATTRIBUTE">
<Element>ELEMENT</Element>
</sample1>
</DocumentElement>
DataTable.WriteXmlSchema()では次のように出力されます。
<?xml version="1.0" standalone="yes"?>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="sample1" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="sample1">
<xs:complexType>
<xs:sequence>
<xs:element name="Element" type="xs:string" minOccurs="0" msdata:Ordinal="0" />
</xs:sequence>
<xs:attribute name="Attribute" type="xs:string" />
<xs:attribute name="Hidden" type="xs:string" use="prohibited" />
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
SimpleContentは単独で指定します。
DataTable table2 = new DataTable("sample2");
table2.Columns.Add("SimpleContent").ColumnMapping = MappingType.SimpleContent;
//table2.Columns.Add("SimpleContent2").ColumnMapping = MappingType.SimpleContent; // ArgumentException「入れ子にされたリレーションシップまたは要素列を、SimpleContent 列を含むテーブルに追加することはできません。」
table2.Rows.Add("SIMPLECONTENT");
table2.WriteXml("sample2.xml");
table2.WriteXmlSchema("sample2.xsd");
DataTable.WriteXml()の出力
<?xml version="1.0" standalone="yes"?> <DocumentElement xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <sample2>SIMPLECONTENT</sample2> </DocumentElement>
DataTable.WriteXmlSchema()の出力
<?xml version="1.0" standalone="yes"?>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="sample2" msdata:UseCurrentLocale="true">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element name="sample2" nillable="true">
<xs:complexType>
<xs:simpleContent msdata:ColumnName="SimpleContent" msdata:Ordinal="0">
<xs:extension base="xs:string">
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
</xs:schema>
ColumnMappingをMappingType.Attributeとしたとき、DataColumn.DataTypeの型によってはWriteXml()などで出力するときに「'***' 型の DataColumn は complexType です。複合型の値を Attribute としてシリアル化することはできません (DataColumn with type '***' is a complexType. Can not serialize value of a complex type as Attribute.)」としてArgumentExceptionが投げられることがあります。その場合には、MappingType.Attribute以外を指定します。
Attributeを指定できるのはDataStorage.GetStorageType()で得られる型のみのため、単純型などの基本型 (プリミティブ型) やSqlInt32などのSQL Serverのネイティブ データ型のみです。よってその型のメンバにXmlAttributeを指定するなどして、XMLの属性として出力できるようにしても使用できません。
RowFilterと同様の式を指定することで、値に演算結果を設定できます。DataColumn.Expression Property (System.Data) | Microsoft Learn
DataTable table = new DataTable();
table.Columns.Add("A", typeof(int));
table.Columns.Add("B", typeof(int));
DataColumn column = table.Columns.Add("C", typeof(int));
column.Expression = "A + B";
DataRow row = table.Rows.Add(1, 2);
int r = row.Field<int>(column); // 3