いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

ADO.NET入門記-014 (System.Data.DataTableついて(01) (DataTable, DataRow, DataColumn))

今回から、数回に分けてSystem.Data.DataTableクラスについて
記述していきます。


既にずっと前から、暗黙的に使用されてきているクラスですが、やはりADO.NETを勉強する上で
かかせないクラスとなりますので、一つ一つメソッドを使用してみようと思います。


ADO.NETを使用する上で、最も重要だと思うクラスは以下の通りです。

System.Data.DataSet
System.Data.DataTable
System.Data.DataRow
System.Data.DataRowState
System.Data.DataColumn
System.Data.Common.DbConnection
System.Data.Common.DbCommand
System.Data.Common.DbDataAdapter
System.Transactions.TransactionScope

データセットデザイナなどを利用して、データセットを自動生成しても
実際に使用する際には、上記のクラスに対しての基礎知識が必要となります。


今回は、データテーブルを手動で構築してみます。
VisualStudioにて、型付けのデータテーブルが自動生成されますが実際には
XSDファイルに定義されたカラム名のプロパティが定義され、内部では今回の
ようにデータテーブルに対してカラム定義がされているだけです。基本は同じです。


以下、サンプルです。

using System;
using System.Data;
using System.Data.Common;
using System.Collections.Generic;

using NUnit.Framework;

namespace Gsf.Samples.AdoNet {

    [TestFixture]
    public class AdoNetSample015 {

        /// 
        /// DataTableオブジェクトの機能を確認するためのテストメソッドです。
        /// 
        /// 
        /// 今回は、DataTableオブジェクトを手動で構築する部分について、テストしてみます。
///
[Test] public void DataTableオブジェクトの機能確認(){ // // DataTableオブジェクトを構築. // // コンストラクタの引数には、何も無しか、文字列でテーブル名を指定します。 // DataTable table = new DataTable("TestTable"); PrintTableInformation(table); // // 生成したデータテーブルに、カラム定義を行なう. // // カラム定義を行なうには、System.Data.DataColumnクラスのインスタンスを作成する。 // // 通常良く使用されるのは、コンストラクタカラム名とそのカラムのデータ型を // 指定するタイプのもの。 // DataColumn idColumn = new DataColumn("Id", typeof(int)); DataColumn nameColumn = new DataColumn("Name", typeof(string)); DataColumn ageColumn = new DataColumn("Age", typeof(int)); // データテーブルにカラムオブジェクトを追加する事により、カラム定義が行なわれる。 table.Columns.AddRange(new DataColumn{ idColumn, nameColumn, ageColumn }); // // 定義したカラムに制約を追加する。 // // 以下の制約を追加する。 // ・Idカラムは、主キーとする。 // ・Nameカラムは、Not Nullとする。 // ・NameカラムとAgeカラムの値で、ユニークとする。 // // IdカラムをPrimary Keyに指定. table.PrimaryKey = new DataColumn{idColumn}; // NameプロパティにNot Nullを指定. nameColumn.AllowDBNull = false; // Unique制約を生成し、追加. table.Constraints.Add( new UniqueConstraint(new DataColumn[]{nameColumn, ageColumn}) ); // // 行データを追加する。 // // 行データの追加は、いくつかの方法があるが今回は一番ベーシックなものを // 行なう。以下の手順となる。 // // 1.NewRowメソッドを利用して、新規行をデータテーブルオブジェクトに生成してもらう。 // 2.生成された行データに対して、各データを設定. // 3.データテーブルのAddRowメソッドを使用して、データテーブルに追加する。 // for(int i = 0; i < 5; i++){ DataRow newRow = table.NewRow(); newRow[idColumn] = (i + 1); newRow[nameColumn] = string.Format("gsf_zero{0}", (i + 1)); newRow[ageColumn] = (28 + i); table.Rows.Add(newRow); } PrintTableInformation(table); // // データテーブル内の変更を確定. // table.AcceptChanges(); PrintTableInformation(table); } private void PrintTableInformation(DataTable targetTable){ Console.WriteLine("================================================================"); Console.WriteLine(string.Format("テーブル名:{0}", targetTable.TableName)); if(targetTable.Rows.Count != 0) { for(int i = 0; i < targetTable.Rows.Count; i++){ Console.WriteLine("\t行-{0}, 行状態(RowState) = {1}", (i + 1), targetTable.Rows[i].RowState); foreach(DataColumn col in targetTable.Columns){ Console.WriteLine("\t\t{0} = {1}", col.ColumnName, targetTable.Rows[i][col]); } } } Console.WriteLine("================================================================"); } } }

上記を実行すると、以下のように表示されます。

================================================================
テーブル名:TestTable
================================================================
================================================================
テーブル名:TestTable
	行-1, 行状態(RowState) = Added
		Id = 1
		Name = gsf_zero1
		Age = 28
	行-2, 行状態(RowState) = Added
		Id = 2
		Name = gsf_zero2
		Age = 29
	行-3, 行状態(RowState) = Added
		Id = 3
		Name = gsf_zero3
		Age = 30
	行-4, 行状態(RowState) = Added
		Id = 4
		Name = gsf_zero4
		Age = 31
	行-5, 行状態(RowState) = Added
		Id = 5
		Name = gsf_zero5
		Age = 32
================================================================
================================================================
テーブル名:TestTable
	行-1, 行状態(RowState) = Unchanged
		Id = 1
		Name = gsf_zero1
		Age = 28
	行-2, 行状態(RowState) = Unchanged
		Id = 2
		Name = gsf_zero2
		Age = 29
	行-3, 行状態(RowState) = Unchanged
		Id = 3
		Name = gsf_zero3
		Age = 30
	行-4, 行状態(RowState) = Unchanged
		Id = 4
		Name = gsf_zero4
		Age = 31
	行-5, 行状態(RowState) = Unchanged
		Id = 5
		Name = gsf_zero5
		Age = 32
================================================================

1 passed, 0 failed, 0 skipped, took 1.05 seconds.


また、上記のサンプルでは制約を定義しているので、例えば以下のような
行データを後から追加しようとするとエラーとなります。

DataRow errorRow = table.NewRow();

errorRow[idColumn]   = 100;
errorRow[nameColumn] = DbNull.Value;
// エラー:Nameの値を指定していない。(not null制約)
table.Rows.Add(errorRow);

errorRow[idColumn]   = 1;
errorRow[nameColumn] = "Dummy Value";
// エラー:Idの値が重複している(Primary Key制約)
table.Rows.Add(errorRow);

errorRow[idColumn]   = 100;
errorRow[nameColumn] = "gsf_zero1";
errorRow[ageColumn]  = 28;
// エラー:NameとAgeの組み合わせが既に存在している。(Unique制約)
table.Rows.Add(errorRow)