- PR -

[C# ADO.NET] DataSetで参照専用の仮想的な表を作成したい

1
投稿者投稿内容
ひろし
ぬし
会議室デビュー日: 2002/09/16
投稿数: 390
お住まい・勤務地: 兵庫県
投稿日時: 2005-08-20 02:35
<質問>
DataSet内の複数の表を結合することはできるのですが、
このままでは、いちいち表の間を移動しなければ結果が得られないので不便です。
仮想的な表のようなものを作成するにはどうすれば良いのでしょうか?

※この例題は質問のために作成したものです。
オフラインのDataSetでどの程度のことができるか知りたいのです。
従って、オフラインのDataSetの範囲で処理するという前提で回答を願います。

<例題>


// 多数のマスター表と1つの実績表があるとする
// オフラインのDataSetで処理する



DataSet ds1 = new DataSet("製品");

DataTable dt1 = new DataTable("製品在庫実績");
dt1.Columns.Add("ロット",typeof(System.String));
dt1.Columns.Add("品種ID",typeof(System.Int32));
dt1.Columns.Add("倉庫ID",typeof(System.Int32));
dt1.Columns.Add("数量",typeof(System.Int32));
ds1.Tables.Add(dt1);

DataTable dt2 = new DataTable("品種マスター");
dt2.Columns.Add("品種ID",typeof(System.Int32));
dt2.Columns.Add("品種名",typeof(System.String));
ds1.Tables.Add(dt2);

DataTable dt3 = new DataTable("倉庫マスター");
dt3.Columns.Add("倉庫ID",typeof(System.Int32));
dt3.Columns.Add("倉庫名",typeof(System.String));
ds1.Tables.Add(dt3);

DataRelation r2 = new DataRelation( "品種ID",dt2.Columns["品種ID"],dt1.Columns["品種ID"]);
ds1.Relations.Add(r2);

DataRelation r3 = new DataRelation( "倉庫ID",dt3.Columns["倉庫ID"],dt1.Columns["倉庫ID"]);
ds1.Relations.Add(r3);

for(int i = 0;i < 5;i++)
{
DataRow dr2 = dt2.NewRow();
dr2["品種ID"] = i;
dr2["品種名"] = String.Format("品種{0}",i);
dt2.Rows.Add(dr2);
}

for(int i = 0;i < 5;i++)
{
DataRow dr3 = dt3.NewRow();
dr3["倉庫ID"] = i;
dr3["倉庫名"] = String.Format("倉庫{0}",i);
dt3.Rows.Add(dr3);
}

DataRow dr1a = dt1.NewRow();
dr1a["ロット"] = "LOT1001";
dr1a["品種ID"] = 1;
dr1a["倉庫ID"] = 2;
dr1a["数量"] = 10;
dt1.Rows.Add(dr1a);

dr1a = dt1.NewRow();
dr1a["ロット"] = "LOT1002";
dr1a["品種ID"] = 2;
dr1a["倉庫ID"] = 3;
dr1a["数量"] = 10;
dt1.Rows.Add(dr1a);

DataRow drX;
string lot;
int id2;
int id3;
DataRow drX2;
DataRow drX3;
string hinsyu;
string souko;
for(int i = 0;i < dt1.Rows.Count;i++)
{
drX = dt1.Rows[i];
lot = drX["ロット"] as string;
id2 = (int)drX["品種ID"];
id3 = (int)drX["倉庫ID"];
drX2 = drX.GetParentRow(r2,DataRowVersion.Current);
drX3 = drX.GetParentRow(r3,DataRowVersion.Current);
hinsyu = drX2["品種名"] as string;
souko = drX3["倉庫名"] as string;
}
dataGrid1.DataSource = dt1;

//
// マスターテーブルを参照するのに毎回GetParentRow()を使うのは面倒である
// ユーザーに公開するための参照専用の表を作成したい
// "ロット","品種名","倉庫名","数量" 列で構成される仮想的な表(VIEW表)を作成できないか?
//

ほげた
ベテラン
会議室デビュー日: 2002/05/08
投稿数: 67
お住まい・勤務地: なごやん
投稿日時: 2005-08-20 03:09
DataRelationが定義されていて、参照専用ということでしたら
DataColumn.Expressionを使うのはどうでしょうか。
ひろし
ぬし
会議室デビュー日: 2002/09/16
投稿数: 390
お住まい・勤務地: 兵庫県
投稿日時: 2005-08-20 08:17
ご回答ありがとうございます。

DataColumn.Expressionを試してみたのですが、計算式の記述方法が分かりません。

<例題>
例題の続きに"在庫一覧表示"という名前の参照専用の表の作成を試みたが、
実行時エラーが発生してしまった。

… 続き
//
// マスターテーブルを参照するのに毎回GetParentRow()を使うのは面倒である
// ユーザーに公開するための参照専用の表を作成したい
// "ロット","品種名","倉庫名","数量" 列で構成される仮想的な表(VIEW表)を作成できないか?
//

DataTable dt4 = new DataTable("在庫一覧表示");

// 計算列を定義したいのですがエラーが発生してしまう
// 計算列は同一の表同士でしか定義できないのでしょうか?
// エラーメッセージ
// 追加情報 : 構文エラー : '["ロット"]' 演算子の後にオペランドがありません
DataColumn dc1 = new DataColumn("ロット",typeof(System.String),@"dt1.Columns[""ロット""]");
// 追加情報 : 構文エラー : '["品種名"]' 演算子の後にオペランドがありません
DataColumn dc2 = new DataColumn("品種名",typeof(System.String),@"dt2.Columns[""品種名""]");
// 追加情報 : 構文エラー : '["倉庫名"]' 演算子の後にオペランドがありません
DataColumn dc3 = new DataColumn("倉庫名",typeof(System.String),@"dt3.Columns[""在庫名""]");
// 追加情報 : 構文エラー : '["数量"]' 演算子の後にオペランドがありません
DataColumn dc4 = new DataColumn("数量",typeof(System.Int32),@"dt1.Columns[""数量""]");

dt4.Columns.Add(dc1);
dt4.Columns.Add(dc2);
dt4.Columns.Add(dc3);
dt4.Columns.Add(dc4);
にしざき
ぬし
会議室デビュー日: 2003/06/30
投稿数: 304
投稿日時: 2005-08-20 17:36
ついこの間調べたなぁ… とそのときのことを思い出しつつ、
DataColumn.Expression
に Parent とか Child(RelationName) という例があるので、
Parent(RelationName) でいいんじゃなかったかと思うのですが、試していません。
ひろし
ぬし
会議室デビュー日: 2002/09/16
投稿数: 390
お住まい・勤務地: 兵庫県
投稿日時: 2005-08-20 22:51
ご回答ありがとうございます。

Parent()で色々試してみましたが、どうやってもエラーが発生します。
結局、使い方がよく分かりません。アドバイス願います。

例題を作成しましたが、2つ疑問があります。宜しくお願いします。

// 多数のマスター表と1つの実績表があるとする

DataSet ds1 = new DataSet("製品");

DataTable dt1 = new DataTable("製品在庫実績");
dt1.Columns.Add("ロット",typeof(System.String));
dt1.Columns.Add("品種ID",typeof(System.Int32));
dt1.Columns.Add("倉庫ID",typeof(System.Int32));
dt1.Columns.Add("数量",typeof(System.Int32));
ds1.Tables.Add(dt1);

DataTable dt2 = new DataTable("品種マスター");
dt2.Columns.Add("品種ID",typeof(System.Int32));
dt2.Columns.Add("品種名",typeof(System.String));
dt2.Columns["品種ID"].Unique = true;
dt2.Columns["品種名"].Unique = true;
dt2.Columns["品種ID"].AllowDBNull = false;
dt2.Columns["品種名"].AllowDBNull = false;
ds1.Tables.Add(dt2);

DataTable dt3 = new DataTable("倉庫マスター");
dt3.Columns.Add("倉庫ID",typeof(System.Int32));
dt3.Columns.Add("倉庫名",typeof(System.String));
dt3.Columns["倉庫ID"].Unique = true;
dt3.Columns["倉庫名"].Unique = true;
dt3.Columns["倉庫ID"].AllowDBNull = false;
dt3.Columns["倉庫名"].AllowDBNull = false;
ds1.Tables.Add(dt3);

DataRelation re2 = new DataRelation( "品種ID",dt2.Columns["品種ID"],dt1.Columns["品種ID"]);
ds1.Relations.Add(re2);
DataRelation re3 = new DataRelation( "倉庫ID",dt3.Columns["倉庫ID"],dt1.Columns["倉庫ID"]);
ds1.Relations.Add(re3);

//
// 疑問1
// 計算式をどう記述すればよいか分からない
// 品種IDと倉庫IDをたどって品種マスターと倉庫マスターから品種名と倉庫名を受け取る計算式を作成したい
//
dt1.Columns.Add("品種名",typeof(System.String),"Parent(re2).品種名");
dt1.Columns.Add("倉庫名",typeof(System.String),"Parent(re3).倉庫名");

for(int i = 0;i < 5;i++)
{
DataRow dr2a = dt2.NewRow();
dr2a["品種ID"] = i;
dr2a["品種名"] = String.Format("品種{0}",i);
dt2.Rows.Add(dr2a);
}

for(int i = 0;i < 5;i++)
{
DataRow dr3a = dt3.NewRow();
dr3a["倉庫ID"] = i;
dr3a["倉庫名"] = String.Format("倉庫{0}",i);
dt3.Rows.Add(dr3a);
}

//
// 疑問2
// 計算列を含む場合、Rowの作成はどう記述すれば良いのか?
// 疑問1が解決しても多分ここでエラーが発生するような気がします
//
DataRow dr1a = dt1.NewRow();
dr1a["ロット"] = "LOT1001";
dr1a["品種ID"] = 1;
dr1a["倉庫ID"] = 2;
dr1a["数量"] = 10;
dt1.Rows.Add(dr1a);

dr1a = dt1.NewRow();
dr1a["ロット"] = "LOT1002";
dr1a["品種ID"] = 2;
dr1a["倉庫ID"] = 3;
dr1a["数量"] = 10;
dt1.Rows.Add(dr1a);

dataGrid1.DataSource = dt1;


ほげた
ベテラン
会議室デビュー日: 2002/05/08
投稿数: 67
お住まい・勤務地: なごやん
投稿日時: 2005-08-20 23:17
Parent/Childにはリレーション名として
DataRelationの作成時に指定した名前を指定する必要があります。
コード:
dt1.Columns.Add("品種名",typeof(System.String),"Parent(品種ID).品種名");
dt1.Columns.Add("倉庫名",typeof(System.String),"Parent(倉庫ID).倉庫名");


のようにしてみてください。
ひろし
ぬし
会議室デビュー日: 2002/09/16
投稿数: 390
お住まい・勤務地: 兵庫県
投稿日時: 2005-08-21 00:53
ご回答ありがとうございます。
ご指摘の箇所を修正したところ正常に動作しました。
1

スキルアップ/キャリアアップ(JOB@IT)