96
http://biki.jp.net/enterprisenet DataSet プログラミング入門

エンタープライズ.Net DataSet

Embed Size (px)

DESCRIPTION

DataSetプログラミング入門

Citation preview

Page 1: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

DataSet プログラミング入門

Page 2: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

内容

目的 ADO.NETの主要機能であるDataSetの基本的なプログラミング手法を理解する

アジェンダ ADO.NETの概要

DataSetの概要

型付DataSetの定義

データベースからデータの読込

DataSetデータのアクセス

DataSetデータの編集

DataSetの利用

DataSet応用&Tips

Page 3: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

ADO.NETの概要

Page 4: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

ADO.NETの概要

ADO.NET の主要コンポーネント DataSet .NET データプロバイダ

DataSet ADO.NET の非接続型アーキテクチャの中心となるコンポーネント データの行と列で構成される複数の DataTableのコレクションから構成 DataTableオブジェクトはデータに関する主キー、外部キー、制約および、リレーションシップ情報から構成されている

.NET データプロバイダ Connectionオブジェクトはデータソースとの接続機能を提供 Commandオブジェクトによってデータベースコマンドにアクセス DataReaderはデータソースからの高いパフォーマンスの読み取り機能 DataAdapterは DataSetオブジェクトとデータベースの間のブリッジを提供

Page 5: エンタープライズ.Net DataSet

DataSetの概要

DataSet

DataRow(行)

DataTable

DataColumn(列)

DataTable

(テーブル)

DataTable

DataRelation

Constraint(制約)

(リレーション)

DataView

Page 6: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

DataSetの概要

DataTable メモリ常駐データを含む単一テーブルを表現 DataColumn、DataRow、Constraintのコレクションを保持

DataColumn テーブルの列のスキーマ情報 列名、データ型

DataRow テーブルの行データ 現在の変更状態や現在・変更前の複数バージョンのデータを保持

Constraint 列に適用する制約 主キー制約、一意キー制約

DataRelation 2 つの DataTable オブジェクト間の親子のリレーションシップ リレーションシップを利用するとDataSet内部のテーブル間を移動できる

DataView 並べ替え、フィルタ処理などカスタマイズされた DataTable のビューを提供

Page 7: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

型付DataSetの定義

Page 8: エンタープライズ.Net DataSet

定義するサンプルDataSet

pub_id pub_name ….

SampleDataset

publishers テーブル(親)

Title_id title … Pub_id … comment

titles テーブル(子)

Page 9: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データセットの作成

① プロジェクト-新しい項目の追加②データセットを選択

Page 10: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

型付DataSetのテーブル定義

大きくは以下の2つの方法を利用 ツールボックスを利用してマニュアルで作成

既存のデータベースのテーブルを利用して作成

サーバーエクスプローラのテーブルをDrag&Drop

Page 11: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

型付DataSetのテーブル定義

複数のテーブルを配置することが可能

TableAdapterは今回不要なので削除しています

追加のテーブルをDrag&Drop

Page 12: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

型付DataSetのリレーション定義

リレーションの作成 複数配置したテーブル間に関係を設定

①子テーブルを右クリックし「追加」-「リレーション」で作成②ウイザードを利用して関連するカラムを設定

Page 13: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データベースからデータの読込

Page 14: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データベースからデータの読込①

テーブルの読み出し

….pub_namepub_id ….pub_namepub_id

SampleDataset

publishers テーブル(親)

… commentPub_id…titleTitle_id … commentPub_id…titleTitle_id

titles テーブル(子)

型付DataSet

DataSet

データベース DataAdapter.Fill

① DataSetのテーブル名を指定

②型付DataSetのテーブルを指定

Page 15: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

テーブルの読み出し

① DataSetのテーブル名を指定

②型付DataSetのテーブルを指定

データベースからデータの読込①

Dim ds As New DataSet()Dim adapter As New OleDbDataAdapter( _

"SELECT * FROM publishers", connectionString)adapter.Fill(ds, "publishers")

Dim ds As New SampleDataset()Dim adapter As New OleDbDataAdapter( _

"SELECT * FROM publishers", connectionString)adapter.Fill(ds.publishers)

Page 16: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

テーブルの読み出し

① DataSetのテーブル名を指定

②型付DataSetのテーブルを指定

データベースからデータの読込①

DataSet ds = new DataSet();OleDbDataAdapter adapter = new OleDbDataAdapter(

"SELECT * FROM publishers", connectionString);adapter.Fill(ds, "publishers");

SampleDataset ds = new SampleDataset();OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * FROM publishers", connectionString);adapter.Fill(ds.publishers);

Page 17: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データベースからデータの読込②

複数テーブルの読み出し

….pub_namepub_id ….pub_namepub_id

SampleDataset

publishers テーブル(親)

… commentPub_id…titleTitle_id … commentPub_id…titleTitle_id

titles テーブル(子)データベース DataAdapter.Fill

Page 18: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データベースからデータの読込②

複数テーブルの読み出し

Dim ds As New SampleDataset()Dim adapterPublishers As New OleDbDataAdapter( _

"SELECT * FROM publishers", connectionString)adapterPublishers.Fill(ds.publishers)

Dim adapterTitles As New OleDbDataAdapter( _"SELECT * FROM titles", connectionString)

adapterTitles.Fill(ds.titles)

Page 19: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データベースからデータの読込②

複数テーブルの読み出し

SampleDataset ds = new SampleDataset();OleDbDataAdapter adapterPublishers = new OleDbDataAdapter(

"SELECT * FROM publishers", connectionString);adapterPublishers.Fill(ds.publishers);

OleDbDataAdapter adapterTitles = new OleDbDataAdapter("SELECT * FROM titles", connectionString);

adapterTitles.Fill(ds.titles);

Page 20: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データベースからデータの読込③

データベースの複数テーブルをJoinした結果の読み出し

データベース DataAdapter.Fill

….pub_namepub_id ….pub_namepub_id

SampleDataset

publishers テーブル(親)

… commentPub_id…titleTitle_id … commentPub_id…titleTitle_id

titles テーブル(子)

Page 21: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データベースからデータの読込③

データベースの複数テーブルをJoinした結果の読み出し

Dim adapterTitles As New OleDbDataAdapter( _"SELECT titles.*, publishers.pub_name AS comment FROM

titles INNER JOIN publishers ON titles.pub_id = publishers.pub_id", connectionString)

adapterTitles.Fill(ds.titles)

Page 22: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データベースからデータの読込③

データベースの複数テーブルをJoinした結果の読み出し

OleDbDataAdapter adapterTitles = new OleDbDataAdapter(“SELECT titles.*, publishers.pub_name AS comment FROM titles INNER JOIN publishers ON titles.pub_id =publishers.pub_id", connectionString);

adapterTitles.Fill(ds.titles);

Page 23: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データベースからデータの読込④ DataSet内の他のテーブルデータの利用

pub_id pub_name ….

1 AAAA

2 BBBB

Title_id title … Pub_id … comment

1 AAAA

1 AAAA

2 BBBB

titles テーブル(子)

Titlesのcomment列に親テーブルであるpublishersの関連する行の値が自動的に設定される

Expression = "Parent.pub_name"

publishers テーブル(親)

Page 24: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データベースからデータの読込④

Dim ds As New SampleDataset()ds.titles.commentColumn.Expression = "Parent.pub_name"

Dim adapterPublishers As New OleDbDataAdapter( _"SELECT * FROM publishers", connectionString)

adapterPublishers.Fill(ds.publishers)

Dim adapterTitles As New OleDbDataAdapter( _"SELECT * FROM titles", connectionString)

adapterTitles.Fill(ds.titles)

DataSet内の他のテーブルデータの利用

ヘッダー/明細型のDataSetで明細行にヘッダーカラムを表示したい場合などにも利用

Page 25: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データベースからデータの読込④

SampleDataset ds = new SampleDataset();ds.titles.commentColumn.Expression = "Parent.pub_name";

OleDbDataAdapter adapterPublishers = new OleDbDataAdapter("SELECT * FROM publishers", connectionString);

adapterPublishers.Fill(ds.publishers);

OleDbDataAdapter adapterTitles = new OleDbDataAdapter("SELECT * FROM titles", connectionString);

adapterTitles.Fill(ds.titles);

DataSet内の他のテーブルデータの利用

ヘッダー/明細型のDataSetで明細行にヘッダーカラムを表示したい場合などにも利用

Page 26: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

DataColumn.Expressionによる計算列

UnitPrice * 0.086 UnitPrice列 * 0.086 の計算結果

Count(OrderID)列の総数

UnitPrice * Quantity UnitPrice列 * Quantity列 の計算結果

Parent.Price親テーブルの関連する行のPrice列の値

Avg(Child(Orders2Details).Price) Orders2Details リレーションで関連する子テーブルのPriceの平均

Sum(Price) Priceの合計

Convert(total, ‘System.Int32’) 型変換

Len(ItemName) 文字列長

IsNull(price, -1) Nullチェック

IIF(total>1000, ‘expensive’, ‘dear’)条件式

SUBSTRING(phone, 7, 8)文字列の取り出し

Page 27: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

DataSetデータのアクセス

Page 28: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

テーブル( DataTable )へのアクセス

DataSetのTablesプロパティを利用してアクセス

型付DataSetではTable名で直接アクセス可

型付DataSetではTableごとにDataTableの派生クラスが提供される

….pub_namepub_id ….pub_namepub_id

SampleDataset

publishers テーブル(親)

… commentPub_id…titleTitle_id … commentPub_id…titleTitle_id

titles テーブル(子)

SampleDataset.titlesDataTable クラス

SampleDataset.publishersDataTable クラス

Page 29: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

テーブル( DataTable )へのアクセス

'テーブル数の取得tablesCount = ds.Tables.Count'テーブルオブジェクトの宣言Dim table As DataTable'1番目のテーブルを取得table = ds.Tables(0)'テーブル名がpublishersのテーブルを取得table = ds.Tables("publishers")

'テーブル数の取得tablesCount = typedDs.Tables.Count'型付テーブルオブジェクトの宣言Dim typedTable As SampleDataset.publishersDataTable'publishersテーブルを取得typedTable = typedDs.publishers

型付DataSet

DataSet

Page 30: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

テーブル( DataTable )へのアクセス

//テーブル数の取得tablesCount = ds.Tables.Count;//テーブルオブジェクトの宣言DataTable table;//1番目のテーブルを取得table = ds.Tables[0];//テーブル名がpublishersのテーブルを取得table = ds.Tables["publishers"];

//テーブル数の取得tablesCount = typedDs.Tables.Count;//型付テーブルオブジェクトの宣言SampleDataset.publishersDataTable typedTable;//publishersテーブルを取得typedTable = typedDs.publishers;

型付DataSet

DataSet

Page 31: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

列(DataColumn)へのアクセス

DataTableのColumnsプロパティを利用してアクセス

型付DataSetではカラム名付与されたプロパティで直接アクセス可

….pub_namepub_id ….pub_namepub_id

SampleDataset

publishers テーブル(親)

… commentPub_id…titleTitle_id … commentPub_id…titleTitle_id

titles テーブル(子)typedTable.pub_nameColumn プロパティ

Page 32: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

列(DataColumn)へのアクセス

'列数の取得columnsCount = table.Columns.Count'列オブジェクトの宣言Dim column As DataColumn'テーブルの2列目の定義情報を取得column = table.Columns(1)'テーブルのpub_name列目の定義情報を取得column = table.Columns("pub_name")

'列数の取得columnsCount = typedTable.Columns.Count'テーブルのpub_name列目の定義情報を取得column = typedTable.pub_nameColumn

型付DataSet

DataSet

Page 33: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

列(DataColumn)へのアクセス

//列数の取得columnsCount = table.Columns.Count;//列オブジェクトの宣言DataColumn column;//テーブルの2列目の定義情報を取得column = table.Columns[1];//テーブルのpub_name列の定義情報を取得column = table.Columns["pub_name"];

//列数の取得columnsCount = typedTable.Columns.Count;//テーブルのpub_name列目の定義情報を取得column = typedTable.pub_nameColumn;

型付DataSet

DataSet

Page 34: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

行(DataRow)・データへのアクセス

DataTableのRowsプロパティを利用してアクセス

型付DataSetではTableごとにDataRowの派生クラスが提供される

….pub_namepub_id ….pub_namepub_id

SampleDataset

publishers テーブル(親)

… commentPub_id…titleTitle_id … commentPub_id…titleTitle_id

titles テーブル(子)SampleDataset.publishersRow クラス

SampleDataset.titlesRow クラス

Page 35: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

行(DataRow)・データへのアクセス

'行数の取得(0の場合は行がない)rowsCount = table.Rows.Count'行オブジェクトの宣言Dim row As DataRow'テーブルの1行目を取得row = table.Rows(0)'pub_name列の値を取得pub_name = DirectCast(row("pub_name"), String)'テーブルから直接1行目の2番目の列(pub_name)の値を取得pub_name = DirectCast(table.Rows(0)(1), String)'テーブルから直接1行目のpub_nameの列の値を取得pub_name = DirectCast(table.Rows(0)("pub_name"), String)

DataSet

Page 36: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

行(DataRow)・データへのアクセス

'行数の取得(0の場合は行がない)rowsCount = typedTable.Rows.Count'型付行オブジェクトの宣言Dim typedRow As SampleDataset.publishersRow'テーブルの1行目を取得typedRow = typedTable(0)'pub_name列の値を取得pub_name = typedRow.pub_name'テーブルから直接1行目のpub_nameの列の値を取得pub_name = typedTable(0).pub_name

型付DataSet

Page 37: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

行(DataRow)・データへのアクセス

//行数の取得(0の場合は行がない)rowsCount = table.Rows.Count;//行オブジェクトの宣言DataRow row;//テーブルの1行目を取得row = table.Rows[0];//pub_name列の値を取得pub_name = (string)row["pub_name"];//テーブルから直接1行目の2番目の列(pub_name)の値を取得pub_name = (string)table.Rows[0][1];//テーブルから直接1行目のpub_nameの列の値を取得pub_name = (string)table.Rows[0]["pub_name"];

DataSet

Page 38: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

行(DataRow)・データへのアクセス

//行数の取得(0の場合は行がない)rowsCount = typedTable.Rows.Count;//型付行オブジェクトの宣言SampleDataset.publishersRow typedRow;//テーブルの1行目を取得typedRow = typedTable[0];//pub_name列の値を取得pub_name = typedRow.pub_name;//テーブルから直接1行目のpub_nameの列の値を取得pub_name = typedTable[0].pub_name;

型付DataSet

Page 39: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

リレーションを利用したアクセス

RowのGetChildRowsメソッド(親から子)・GetParentRowプロパティ(子から親)を利用してアクセス

型付DataSetではアクセス用メソッド・プロパティが提供される

….pub_namepub_id ….pub_namepub_id

SampleDataset

publishers テーブル(親)

… commentPub_id…titleTitle_id … commentPub_id…titleTitle_id

titles テーブル(子)

GettitlesRows メソッド

publishersRow プロパティ

Page 40: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

リレーションを利用したアクセス(親から子テーブル)

'行オブジェクトの宣言Dim childRows() As DataRow'リレーション名がpublisherstitlesで関連している子の1つ目のtitle列の値を取得

childRows = parentRow.GetChildRows("publisherstitles")title = DirectCast(childRows(0)("title"), String)'上記をまとめて行う場合title = DirectCast(parentRow.GetChildRows("publisherstitles")(0)("title"), String)

'型付行オブジェクトの宣言Dim typedChildRows() As SampleDataset.titlesRow'関連しているtitlesテーブルの1つ目のtitle列の値を取得typedChildRows = typedParentRow.GettitlesRows()title = typedChildRows(0).title'上記をまとめて行う場合title = typedParentRow.GettitlesRows()(0).title

型付DataSet

DataSet

Page 41: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

リレーションを利用したアクセス(子から親テーブル)

'行オブジェクトの宣言Dim parentRow As DataRow'リレーション名がpublisherstitlesで関連している親のpub_name値を取得parentRow = typedChildRows(0).GetParentRow("publisherstitles")pub_name = DirectCast(parentRow("pub_name"), String)'上記をまとめて行う場合pub_name = DirectCast(typedChildRows(0).GetParentRow("publisherstitles")("pub_name"), String)

'型付行オブジェクトの宣言Dim typedParentRow As SampleDataset.publishersRow'親テーブルpublishersのpub_name値を取得typedParentRow = typedChildRows(0).publishersRowpub_name = typedParentRow.pub_name'上記をまとめて行う場合pub_name = typedChildRows(0).publishersRow.pub_name

型付DataSet

DataSet

Page 42: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

リレーションを利用したアクセス(親から子テーブル)

//行オブジェクトの宣言DataRow[] childRows;//リレーション名がpublisherstitlesで関連している子の1つ目のtitle列の値を取得

childRows = parentRow.GetChildRows("publisherstitles");title = (string)childRows[0]["title"];//上記をまとめて行う場合title = (string)parentRow.GetChildRows("publisherstitles")[0]["title"];

//型付行オブジェクトの宣言SampleDataset.titlesRow[] typedChildRows;//関連しているtitlesテーブルの1つ目のtitle列の値を取得typedChildRows = typedParentRow.GettitlesRows();title = typedChildRows[0].title;//上記をまとめて行う場合title = typedParentRow.GettitlesRows()[0].title;

型付DataSet

DataSet

Page 43: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

リレーションを利用したアクセス(子から親テーブル)

DataRow parentRow; //行オブジェクトの宣言//リレーション名がpublisherstitlesで関連している親のpub_name値を取得parentRow = typedChildRows[0].GetParentRow("publisherstitles");pub_name = (string)parentRow["pub_name"];//上記をまとめて行う場合pub_name =(string)

typedChildRows[0].GetParentRow("publisherstitles")["pub_name"];

//型付行オブジェクトの宣言SampleDataset.publishersRow typedParentRow;//親テーブルpublishersのpub_name値を取得typedParentRow = typedChildRows[0].publishersRow;pub_name = typedParentRow.pub_name;//上記をまとめて行う場合pub_name = (string)typedChildRows[0].publishersRow.pub_name;

型付DataSet

DataSet

Page 44: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

主キーを利用した行の検索

DataRowのFindメソッドを利用して行を検索

型付DataSetでは専用の検索メソッドが提供される

….pub_namepub_id ….pub_namepub_id

SampleDataset

publishers テーブル(親)

… commentPub_id…titleTitle_id … commentPub_id…titleTitle_id

titles テーブル(子)

publishersDataTable.FindBypub_id メソッド

titlesDataTable.FindBytitle_id メソッド

検索

検索

Page 45: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

主キーを利用した行の検索

'行オブジェクトの宣言Dim row As DataRow'主キーの値が1389の行を取得row = table.Rows.Find("1389")

'型付行オブジェクトの宣言Dim typedRow As SampleDataset.publishersRow'主キーpub_idの値が1389の行を取得typedRow = typedTable.FindBypub_id("1389")

型付DataSet

DataSet

Page 46: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

主キーを利用した行の検索

//行オブジェクトの宣言DataRow row;//主キーの値が1389の行を取得row = table.Rows.Find("1389");

//型付行オブジェクトの宣言SampleDataset.publishersRow typedRow;//主キーpub_idの値が1389の行を取得typedRow = typedTable.FindBypub_id("1389");

型付DataSet

DataSet

Page 47: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

DataSetデータの編集

Page 48: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

行の追加

DataTableのNewRowメソッドを利用して行を追加

型付DataSetではテーブル毎の追加メソッドが提供される

….pub_namepub_id ….pub_namepub_id

SampleDataset

publishers テーブル(親)

… commentPub_id…titleTitle_id … commentPub_id…titleTitle_id

titles テーブル(子)

publishersDataTable. AddpublishersRow メソッド

titlesDataTable. AddtitlesRow メソッド

追加

追加

Page 49: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

行の追加

'行オブジェクトの作成row = table.NewRow()'データの値の設定row("pub_id") = "pub_id1"row("pub_name") = "pub_name1"row("city") = "city1"row("state") = "state1"row("country") = "country1"'行オブジェクトのテーブルへの追加table.Rows.Add(row)

DataSet

'行オブジェクトのテーブルへの追加typedRow = typedTable.AddpublishersRow( _

"pub_id2", "pub_name2", "city2", "state2", "country2")

型付DataSet

Page 50: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

行の追加

//行オブジェクトの作成row = table.NewRow();//データの値の設定row["pub_id"] = "pub_id1";row["pub_name"] = "pub_name1";row["city"] = "city1";row["state"] = "state1";row["country"] = "country1";//行オブジェクトのテーブルへの追加table.Rows.Add(row);

DataSet

//行オブジェクトのテーブルへの追加typedRow = typedTable.AddpublishersRow("pub_id2", "pub_name2", "city2", "state2", "country2");

型付DataSet

Page 51: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

行の変更

行のアイテムに値を代入

….pub_namepub_id ….pub_namepub_id

SampleDataset

publishers テーブル(親)

… commentPub_id…titleTitle_id … commentPub_id…titleTitle_id

titles テーブル(子)

新しい値

変更

Page 52: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

行の変更

'行オブジェクトの宣言Dim row As DataRow'行オブジェクトの取得row = table.Rows(0)'データの値の変更row("pub_name") = "pub_name1"row("city") = "city1"

'型付行オブジェクトの宣言Dim typedRow As SampleDataset.publishersRow'行オブジェクトの取得typedRow = typedTable(0)'データの値の変更typedRow.pub_name = "pub_name2"typedRow.city = "city2"

型付DataSet

DataSet

Page 53: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

行の変更

//行オブジェクトの宣言DataRow row;//行オブジェクトの取得row = table.Rows[0];//データの値の変更row["pub_name"] = "pub_name1";row["city"] = "city1";

//型付行オブジェクトの宣言SampleDataset.publishersRow typedRow;//行オブジェクトの取得typedRow = typedTable[0];//データの値の変更typedRow.pub_name = "pub_name2";typedRow.city = "city2";

型付DataSet

DataSet

Page 54: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

行の削除

DataRowのDeleteメソッドを利用して行を削除

….pub_namepub_id ….pub_namepub_id

SampleDataset

publishers テーブル(親)

… commentPub_id…titleTitle_id … commentPub_id…titleTitle_id

titles テーブル(子)

削除

削除

Page 55: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

行の削除

'2番目の行オブジェクトの削除table.Rows(1).Delete()'主キーで行オブジェクトの削除Dim row As DataRowrow = table.Rows.Find("1389")row.Delete()

'主キーで行オブジェクトの削除Dim typedRow As SampleDataset.publishersRowtypedRow = typedTable.FindBypub_id("9999")typedRow.Delete()

型付DataSet

DataSet

Page 56: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

行の削除

//2番目の行オブジェクトの削除table.Rows[1].Delete();//主キーで行オブジェクトの削除DataRow row;row = table.Rows.Find("1389");row.Delete();

//主キーで行オブジェクトの削除SampleDataset.publishersRow typedRow;typedRow = typedTable.FindBypub_id("9999");typedRow.Delete();

型付DataSet

DataSet

Page 57: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

変更データの確定と破棄

変更の確定 AcceptChangesメソッド

変更の破棄 RejectChangesメソッド DataSet,DataTable,DataRow単位で利用可能

….pub_namepub_id ….pub_namepub_id

SampleDataset

publishers テーブル(親)

… commentPub_id…titleTitle_id … commentPub_id…titleTitle_id

titles テーブル(子)

DataSet. AcceptChanges

DataSet. RejectChanges

DataTable. AcceptChanges

DataTable. RejectChanges

DataRow. AcceptChanges

DataRow. RejectChanges

Page 58: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

変更データの確定と破棄

Dim row As DataRowrow = table.Rows(0)row("pub_name") = "pub_name1"row("city") = "city1"'変更した行データの確定(行単位)row.AcceptChanges()

row = table.Rows(1)row("pub_name") = "pub_name1"row("city") = "city1"row = table.Rows(2)row("pub_name") = "pub_name1"row("city") = "city1"'変更したデータの確定(DataSet全体)ds.AcceptChanges()

Page 59: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

変更データの確定と破棄

Dim row As DataRowrow = table.Rows(0)row("pub_name") = "pub_name1"row("city") = "city1"'変更したデータの破棄(行単位)row.RejectChanges()

row = table.Rows(1)row("pub_name") = "pub_name1"row("city") = "city1"row = table.Rows(2)row("pub_name") = "pub_name1"row("city") = "city1"'変更したデータの破棄(DataSet全体)ds.RejectChanges()

Page 60: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

変更データの確定と破棄

DataRow row;row = table.Rows[0];row["pub_name"] = "pub_name1";row["city"] = "city1";//変更した行データの確定(行単位)row.AcceptChanges();

row = table.Rows[1];row["pub_name"] = "pub_name1";row["city"] = "city1";row = table.Rows[2];row["pub_name"] = "pub_name1";row["city"] = "city1";//変更したデータの確定(DataSet全体)ds.AcceptChanges();

Page 61: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

変更データの確定と破棄

DataRow row;row = table.Rows[0];row["pub_name"] = "pub_name1";row["city"] = "city1";//変更したデータの破棄(行単位)row.RejectChanges();

row = table.Rows[1];row["pub_name"] = "pub_name1";row["city"] = "city1";row = table.Rows[2];row["pub_name"] = "pub_name1";row["city"] = "city1";//変更したデータの破棄(DataSet全体)ds.RejectChanges();

Page 62: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

DataSetの利用

Page 63: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データのマージ

DataSetのMergeメソッドを利用してデータをマージすることができる 利用可能なデータソースはDataSet、DataTableとDataRow配列

….pub_namepub_id ….pub_namepub_id

SampleDataset

publishers テーブル(親)

… commentPub_id…titleTitle_id … commentPub_id…titleTitle_id

titles テーブル(子)

….pub_namepub_id ….pub_namepub_id

publishers テーブル(親)

… commentPub_id…titleTitle_id … commentPub_id…titleTitle_id

titles テーブル(子)

Merge

… commentPub_id…titleTitle_id … commentPub_id…titleTitle_id

titles テーブル(子)

DataRow()

DataTable

DataSet

データソース

Page 64: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データのマージ

'1つ目のDataSetにデータを読み込むDim targetDataSet As New SampleDataset()Dim adapterPublishers As New OleDbDataAdapter( _

"SELECT * FROM publishers", connectionString)adapterPublishers.Fill(targetDataSet.publishers)

'2つ目のDataSetにデータを読み込むDim srcDataSet As New DataSet()Dim adapterTitles As New OleDbDataAdapter( _

"SELECT * FROM titles", connectionString)adapterTitles.Fill(srcDataSet, "titles")

'1つ目のDataSetに2つ目のDataSetのデータをマージtargetDataSet.Merge(srcDataSet)

Page 65: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データのマージ

//1つ目のDataSetにデータを読み込むSampleDataset targetDataSet = new SampleDataset();OleDbDataAdapter adapterPublishers = new OleDbDataAdapter(

"SELECT * FROM publishers", connectionString);adapterPublishers.Fill(targetDataSet.publishers);

//2つ目のDataSetにデータを読み込むDataSet srcDataSet = new DataSet();OleDbDataAdapter adapterTitles = new OleDbDataAdapter(

"SELECT * FROM titles", connectionString);adapterTitles.Fill(srcDataSet, "titles");

//1つ目のDataSetに2つ目のDataSetのデータをマージtargetDataSet.Merge(srcDataSet);

Page 66: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

行の特定バージョンへのアクセス

列の値にアクセス際に別バージョン(DataRowVersion ) を指定することで特定のバージョン行にアクセスできる 行の別のバージョンは行の編集後、行で AcceptChanges メソッドが呼び出される前にだけ存在。AcceptChangesメソッドの呼び出し後は、現在のバージョンと元のバージョンが同じになる

1 名前1 住所1 TEL1

1 名前1 住所2 TEL1

初期データ(RowState=Unchanged)

変更データ(RowState=Modified)

1 名前1 住所2 TEL1

確定データ(RowState= Unchanged )

①行のデータを変更

Original バージョン

Current バージョン

②変更データを確定

Page 67: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

行の特定バージョンへのアクセス

'行の状態を取得(Unchanged)stat = table.Rows(0).RowState'データの値の変更row = table.Rows(0)row("pub_name") = "pub_name1"'行の状態を取得(Modified)stat = table.Rows(0).RowState

'変更前データの取得(元データ)Dim originalPubName As String = _

DirectCast(row("pub_name", DataRowVersion.Original), String)'型付DataSetの場合originalPubName = _

DirectCast(typedTable(0)("pub_name", DataRowVersion.Original), String)

'変更データの確定row.AcceptChanges()'変更前データの取得(変更データ)originalPubName = DirectCast(row("pub_name", DataRowVersion.Original), String)

Page 68: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

行の特定バージョンへのアクセス

//行の状態を取得(Unchanged)stat = table.Rows[0].RowState;//データの値の変更row = table.Rows[0];row["pub_name"] = "pub_name1";//行の状態を取得(Modified)stat = table.Rows[0].RowState;

//変更前データの取得(元データ)string originalPubName = (string)row["pub_name", DataRowVersion.Original];

//型付DataSetの場合originalPubName = (string)typedTable[0]["pub_name", DataRowVersion.Original];

//変更データの確定row.AcceptChanges();//変更前データの取得(変更データ)originalPubName = (string)row["pub_name", DataRowVersion.Original];

Page 69: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

DataRowVersionの値

DataRowStateの値

DataRowState ・DataRowVersion

Current この行には現在の値が格納されています

Default 現在の DataRowStateに従った既定の行バージョン

Original この行には元の値が格納されています

Proposed この行には提示された値が格納されています

Added 行が DataRowCollection に追加されましたが、 AcceptChanges が呼び出されていません

Deleted DataRow の Delete メソッドを使用して行が削除されました

Detached 行が作成されましたが、どの DataRowCollection にも追加されていません。 DataRow は、作成された直後からコレクションに追加されるまでの間、またはコレクションから削除された場合に、この状態になります

Modified 行が変更されましたが、 AcceptChanges が呼び出されていません

Unchanged 前回 AcceptChanges が呼び出されて以降、この行は変更されていません。

Page 70: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

変更された行の取得

DataSet(もしくはDataTable)のGetChangesメソッドを利用して変更されたレコードだけをデータセットから抽出できる

pub_id pub_name …

.

1 名前1

2 名前2X

3 名前3

pub_id pub_name ….

2 名前2XGetChanges

変更された行

Page 71: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

変更された行の取得スマートクライアントでの利用例

pub_id pub_name ….

1 名前1

2 名前2X

3 名前3

pub_id pub_name ….

2 名前2X

③ GetChanges

pub_id pub_name ….

1 名前1

2 名前2

3 名前3

②データの変更pub_id pub_name ….

1 名前1

2 名前2X

3 名前3

pub_id pub_name ….

1 名前1

2 名前2

3 名前3

pub_id pub_name ….

2 名前2X

④転送

①転送

⑤マージ

Web サーバークライアント

Page 72: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

変更された行の取得

'編集用のコピーDataSetを作成(クライアントの取得)copyDataSet.Merge(orignalDataSet)

'DataSetの値の変更(クライアントでの編集)copyDataSet.publishers(0).pub_name = "pub_name1"

'差分データの取得(転送データの作成)Dim changeDataSet As SampleDatasetchangeDataSet = DirectCast(copyDataSet.GetChanges(), SampleDataset)MessageBox.Show("差分データ = " + changeDataSet.GetXml())

'元データへの差分データの反映(サーバーへの反映)orignalDataSet.Merge(changeDataSet)

Page 73: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

変更された行の取得

//編集用のコピーDataSetを作成(クライアントの取得)copyDataSet.Merge(originalDataSet);

//DataSetの値の変更(クライアントでの編集)copyDataSet.publishers[0].pub_name = "pub_name1";

//差分データの取得(転送データの作成)SampleDataset changeDataSet;changeDataSet = (SampleDataset)copyDataSet.GetChanges();MessageBox.Show("差分データ = " + changeDataSet.GetXml());

//元データへの差分データの反映(サーバーへの反映)originalDataSet.Merge(changeDataSet);

Page 74: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データのフィルタとソート

DataViewを利用して1つのDataTableをフィルタしたりソートすることができる 複数のDataTableをJoinするようなDataViewは作成できないため、

DataColumnのExpressionを利用した他のテーブル列を取り込んだDataTableをあらかじめ作成しておく

….pub_namepub_id ….pub_namepub_id

SampleDataset

publishers テーブル(親)

… commentPub_id…titleTitle_id … commentPub_id…titleTitle_id

titles テーブル(子)

Title_id title … Pub_id … comment

DataView

フィルタ:DataView.RowFilterプロパティソート:DataView.Sortプロパティ

Page 75: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データのフィルタとソート

'DataViewを利用したフィルタDim dv As New DataView()dv.Table = tabledv.RowFilter = "country='USA'"

'DataViewを利用したソートDim dv As New DataView()dv.Table = tabledv.Sort = "pub_name"

Page 76: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データのフィルタとソート

//DataViewを利用したフィルターDataView dv = new DataView();dv.Table = table;dv.RowFilter = "country='USA'";

//DataViewを利用したソートDataView dv = new DataView();dv.Table = table;dv.Sort = "pub_name";

Page 77: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

カラムの絞り込みと Distinct

DataViewのToTableを利用すると、元のデータの一部のカラムを取り出すことができる

さらに、同じデータを1つにまとめることもできます(Distinct機能 )

'DataViewを利用したDistinctDim view As DataView = New DataView(table)Dim newTable As DataTable = view.ToTable(“UniqueData”, True,"Category", "QuantityInStock")

//DataViewを利用した DistinctDataView view = new DataView(table); DataTable newTable = view.ToTable("UniqueData", true, "Category", "QuantityInStock");

Page 78: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

DataSet応用&Tips

Page 79: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

DBNullのハンドリング

DataColumnのプロパティ AllowDBNull

この列に null (VBでは Nothing)値を格納できるかどうかを示す値

DefaultValue 新しい行を作成するときに使用されるこの列の既定値

DataTableへの行追加時に便利 DataTableのNewRowで作成した行に既定値が設定される

注意 データベースから読み出したNULL値は置換されない

後述するデザイナで指定するNullValueを利用

Page 80: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

DBNullのハンドリング

型付DataSet デザイナでの設定(続き) NullValue

(Throw Exception)(既定値)を指定するとアクセス時にDBNullであれば例外をスロー

(Null) を指定するとDBNullであればnull (VBでは Nothing)を返す (Empty)を指定するとDBNullであればString.Emptyを返す。ただし、文字例の場合のみ指定可能。

その他の値を指定するとDBNullであればその値が返される。 NullValueの利用上の注意

NullValueは型付DataSetで作成されたプログラム上で実現されている機能であり、あくまでも型付DataSetのクラスの生成されたプロパティをアクセスした場合にのみ有効であることに注意

○ typedTable(0).pub_name × table.Rows(0)(“pub_name”) ← DBNullが返える

Page 81: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

参考デザイナで指定可能なカラムのプロパティ

Page 82: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

DBNullの判断と設定

'' DBNull判定If table.Rows(0).IsNull("pub_name") Then

...End If'' DBNull設定table.Rows(0)("pub_name") = System.Convert.DBNull

'' DBNull判定If typedTable(0).Ispub_nameNull() Then

...End If'' DBNull設定typedTable(0).Setpub_nameNull()

型付DataSet

DataSet

Page 83: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

DBNullの判断と設定

//DBNull判定if (table.Rows[0].IsNull("pub_name")){}//DBNull設定table.Rows[0]["pub_name"] = System.Convert.DBNull;

//DBNull判定if (typedTable[0].Ispub_nameNull()) {}//DBNull設定typedTable[0].Setpub_nameNull();

型付DataSet

DataSet

Page 84: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データセットのデータの検証

DataSet自体にデータの有効性の確認を組み込むことができる。主な組み込み方法としては以下の3つ。 制約を利用したデータ検証

キー制約や一意の制約などをデータセットの実際のスキーマ定義の一部として作成する

DataColumnのプロパティの設定

MaxLength、AllowDBNull、Unique など、DataColumn オブジェクトのプロパティを設定する

変更イベントのハンドリング

列および行の変更イベント中にデータをチェックできるアプリケーション固有の検証を作成する

DataGrid(Windowsフォーム)などのデータセットの更新がUIで直接実行される場合に利用されることが多い

Page 85: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データセットのデータの検証制約を利用したデータ検証

主キー NULL でない一意な値を持つ列(1つ以上)として定義することができる。

デザイナで「新しいキー」を追加することで定義することが可能。

一意キー(UniqueConstraint) NULL 値を許可する、一意な値を持つ列(1つ以上)として定義することができる。

デザイナで「新しいキー」を追加することで定義することが可能。1テーブル複数個作成可能。主キーは1つのみ。

Page 86: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データセットのデータの検証制約を利用したデータ検証

キー参照(ForeignKeyConstraint) データベースの外部キーと似たもので、関連付けられているテーブルの更新や追加、削除を制限することができる。

例えば、子供を持つ親レコードの削除の禁止。

デザイナでリレーションを作成して外部キー制約を利用することで可能。DeleteRuleやUpdateRule プロパティで動作を変更することが可能。

Page 87: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データセットのデータの検証DataColumnのプロパティの設定

MaxLength

文字単位で表した列の最大長。列に最大長がない場合の値は -1 (既定)

AllowDBNull

null 値を格納できる場合は true(既定値)

Unique

値が一意である必要がある場合は true 。既定値はfalse

DataSetデザイナで指定する場合は該当列をキーとして設定するとtrueに設定される

Page 88: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データセットのデータの検証制約の一時的な無効化

DataSet.EnforceConstraintsプロパティ DataSet更新処理で制約を有効/無効するプロパティ

trueの場合に自動的に制約のチェックが行われる

falseの場合は制約のチェックは行われない falseからtrueに設定した場合、全ての制約のチェックが行われ、制約に違反していると例外が発生する

DataTableのConstrains制約、DataColumnの制約に対して影響

キー参照が設定されているDataSetに対して、制約を一時的に無効化してテーブルからデータを読み出す例

ds.EnforceConstraints = FalsedaCustomers.Fill(ds)daOrders.Fill(ds)ds.EnforceConstraints = True

ds.EnforceConstraints = false;daCustomers.Fill(ds);daOrders.Fill(ds);ds.EnforceConstraints = true;

Page 89: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データセットのデータの検証変更イベントのハンドリング

ColumnChanging イベント 特定の列の変更を検証する場合に利用。

列の変更直後にエラーを検出することが必要な場合は、ColumnChanging イベントを使って検証。

RowChanging イベント 変更が行のどこかで発生していることを通知。

一度に複数のエラーを検出する場合 RowChanging イベントを利用。特に、1 つの列の値が別の列の内容に基づいて検証されるような方法でデータが構築されている場合は、RowChanging イベント中に検証を実行する必要がある。

一時的に制約を中断する目的でDataRowのBeginEdit メソッドを利用すると、各列がそれぞれ変更された後のRowChanging イベントおよび RowChanged イベントをオフにすることができる。EndEdit メソッドが呼び出されるまで発生しない。

Page 90: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データセットのデータの検証変更イベントのハンドリング

Private Sub table_ColumnChanging( _ByVal sender As Object, ByVal e As DataColumnChangeEventArgs)

''発生したカラム名の確認If e.Column.ColumnName = "pub_name" Then

Dim newValue As String = DirectCast(e.ProposedValue, String)If newValue.Trim().Length > 10 ThenMessageBox.Show("10文字以下で入力してください", "入力エラー")Throw New ApplicationException("10文字以下で入力してください")

End IfEnd If

End Sub

Page 91: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

データセットのデータの検証変更イベントのハンドリング

private void table_ColumnChanging(object sender, DataColumnChangeEventArgs e)

{

//発生したカラム名の確認if (e.Column.ColumnName == "pub_name") {string newValue = (string)(e.ProposedValue);if (newValue.Trim().Length > 10) {

MessageBox.Show("10文字以下で入力してください","入力エラー");throw new ApplicationException("10文字以下で入力してください");

}}

}

Page 92: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

DataSet Tips

DataSetの検索メソッドの利用について

主キーで検索する場合 DataRowCollection.Findメソッドを利用(DataTable.Rows.Findのこと) DataTableには主キーで検索インデックスが生成される

任意の項目・特定バージョンの検索 DataTable.Selectメソッドが利用できる。ただし、Selectメソッドは複雑な検

索が可能な反面オーバーベッドも大きいため、同じ項目を何度も等号検索する処理にはDataViewを作成・利用した検索を行うようにする。

DataViewを利用した検索 DataViewのSortカラムに指定した項目にたいしてFindおよびFindRowsメ

ソッドで検索が可能です。(検索インデックスが生成され利用される) DataViewの検索インデックスはSort、RowFilter 、RowStateFilter プロパ

ティを変更するごとに再作成されるためコンストラクタで必要な値を全て指定するようにする。

RowStateFilterを利用した検索も可能だが検索インデックスが再作成されるためオーバーヘッドが大きくなる。DataGridなどでのフィルタ処理に利用する。

Page 93: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

DataSet TipsDataSetでの検索時の大文字・小文字の区別

SelectやFindメソッドなどはDataTableやDataSetのCaseSensitiveによって区別する/しないが変化する。既定値ではfalseのため大文字/小文字の区別をしない。

ユニークキーのチェックも同様の影響を受ける

型付DataSetに対してはデザイナで設定することが可能。

Page 94: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

DataSet TipsPartial Classの利用

Partialクラスとは 1つのクラスのソースコードを複数のファイルに分散して記述することができるコンパイラの仕組み

Partialクラスを利用することで型付DataSetに新しいプロパティやメソッドを追加することできる DataRow(テーブル名Row)クラスにプロパティを追加すると、データカラムのように利用することが可能

ただし、あくまでも型付DataSetに追加するものなので、非型付DataSetからは利用できない

Page 95: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

DataSet TipsPartial Classの利用

独自の計算式などを実装することが可能 画面のデータバインド処理に便利

partial class AuthorsData {partial class authorsRow {

public int TitleCount {get { return this.GettitleauthorRows().Length; }

}}

}

Partial Class AuthorsDataSetPartial Class authorsRow

Public ReadOnly Property TitleCount() As IntegerGet

Return Me.GettitleauthorRows().LengthEnd Get

End PropertyEnd Class

End Class

Page 96: エンタープライズ.Net DataSet

http://biki.jp.net/enterprisenet

DataSet Tipsシリアライズ

シリアライズの2つのパターン

XMLシリアライズ(XmlSerializerを利用したシリアライズ)

Diffgram形式

DiffGramは、データ要素の現在のバージョンと元のバージョンを識別するXML 形式です。行エラー情報、行順序などの情報も含まれています。

Binaryシリアライズ( BinaryFormatterを利用したシリアライズ)

RemotingFormatを設定することで出力形式を変えることが可能

下位互換のためXml形式が規定値。バイナリ形式で出力するためには明示的にSerializationFormat. Binaryを指定する必要がある

シリアライズの高速化

データが多くなるとBinaryシリアライズの方が高速

SchemaSerializationModeをExcludeSchemaにするとスキーマ情報がシリアライズされないため高速