C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[3]: リレーション子Tableへの新行追加方法について


(過去ログ 30 を表示中)

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■14582 / inTopicNo.1)  リレーション子Tableへの新行追加方法について
  
□投稿者/ 富田 (1回)-(2008/02/22(Fri) 11:44:42)

分類:[.NET 全般] 

C#2005
orcle10g

C#.NET2005で開発している者です。
行き詰ってしまったので質問させて下さい。
DataSetでDataTableに親子関係でリレーションを張ったTableの新行追加更新について質問です。
以下がTableの概要になります。

DataTable:A親
カラムCD1 キー
カラム名称

DataTable:B子
カラムCD1 キー
カラム名称
カラム数量

A親とB子をカラムCD1をキーにして、リレーションを張っています。
A親のデータ1件に対し、B子のデータn件が紐付く関係です。
A親に新行を追加した場合、B子にデフォルトとして、いくつか行を設定する仕様になっています。
その際、B子にA親のカラムCD1の値を入れたいのですが、(※B子.rows[i][カラムCD1] = A親.rows[c][カラムCD1]としてます)
FK_A親_A子_カラムCD1には、A親のカラムCD1の値が必要です等のメッセージと共に、
追加が拒否されてしまいます。
どうすれば良いでしょうか?

引用返信 編集キー/
■14583 / inTopicNo.2)  Re[1]: リレーション子Tableへの新行追加方法について
□投稿者/ はつね (464回)-(2008/02/22(Fri) 11:53:07)
はつね さんの Web サイト
No14582 (富田 さん) に返信
> その際、B子にA親のカラムCD1の値を入れたいのですが、(※B子.rows[i][カラムCD1] = A親.rows[c][カラムCD1]としてます)
> FK_A親_A子_カラムCD1には、A親のカラムCD1の値が必要です等のメッセージと共に、
> 追加が拒否されてしまいます。

DataTableつかっているって事は、親子のDataTable間が別トランザクションになっているはず。
親子を同一トランザクション内にいれて、親をINSERTしてから子をINSERTすればOK。

# 親側をINSERTしてから子側をINSERTでもできるけれどトランザクション制御は必須だと思うので、そこを絡めて実装しましょう。

引用返信 編集キー/
■14584 / inTopicNo.3)  Re[2]: リレーション子Tableへの新行追加方法について
□投稿者/ 富田 (2回)-(2008/02/22(Fri) 12:00:18)
No14583 (はつね さん) に返信
> ■No14582 (富田 さん) に返信
>>その際、B子にA親のカラムCD1の値を入れたいのですが、(※B子.rows[i][カラムCD1] = A親.rows[c][カラムCD1]としてます)
>>FK_A親_A子_カラムCD1には、A親のカラムCD1の値が必要です等のメッセージと共に、
>>追加が拒否されてしまいます。
>
> DataTableつかっているって事は、親子のDataTable間が別トランザクションになっているはず。
> 親子を同一トランザクション内にいれて、親をINSERTしてから子をINSERTすればOK。
>
> # 親側をINSERTしてから子側をINSERTでもできるけれどトランザクション制御は必須だと思うので、そこを絡めて実装しましょう。
>

はつね様、返答、ありがとうございます。
返答を頂き、私の情報の提供不足を認識しました。すいません。
DataTableはDBでなく、ソース上にあります。(XSDなんですが)
また、追加時には、親のDataTableに追加してから、子に入れております。
親のキー項目と同じ値を子のカラムCD1に追加しているのに、
同じ値を設定してくださいと怒られている状態です。

引用返信 編集キー/
■14586 / inTopicNo.4)  Re[1]: リレーション子Tableへの新行追加方法について
□投稿者/ 魔界の仮面弁士 (648回)-(2008/02/22(Fri) 13:02:34)
No14582 (富田 さん) に返信
> DataSetでDataTableに親子関係でリレーションを張ったTableの新行追加更新について質問です。

リレーションをどのように設定し、行をどうやって追加しているのかを提示してもらえますか?
少なくとも、下記のコードでは正常に追加できていますので。


検証に使用した型付DataSetの定義は、こんな感じ。

<DataSet1>:DataSet
 <A親>:DataTable
  <カラムCD1>:Int32, 主キー
  <カラム名称>:String
 <B子>:DataTable
  <カラムCD1>:Int32, 主キー
  <カラム名称>:String
  <カラム数量>:Int32
 <A親_B子>:DataRelation
  ・連結:A親.カラムCD1 = B子.カラムCD1
  ・制約:リレーションシップのみ
  ・入れ子になったリレーションシップ:OFF



DataGrid grid = new DataGrid();
Button button1 = new Button();
Button button2 = new Button();
DataSet1 ds = new DataSet1();
void Form1_Load(object sender, EventArgs e)
{
    this.Size = new Size(400, 300);
    grid.SetBounds(0, 0, 400, 200);
    grid.DataSource = ds;
    Controls.Add(grid);

    // 行の登録方法、その1
    ds.B子.AddB子Row(ds.A親.AddA親Row(1, "あああ"), "アアア", 123);
    ds.B子.AddB子Row(ds.A親.AddA親Row(2, "いいい"), "イイイ", 456);
    ds.B子.AddB子Row(ds.A親.AddA親Row(3, "ううう"), "ウウウ", 789);
    ds.AcceptChanges();

    button1.SetBounds(15, 220, 100, 35);
    button1.Text = "CD=4を追加";
    Controls.Add(button1);
    button1.Click += delegate
    {
        button1.Enabled = false;

        // 行の登録方法、その2
        ds.A親.Rows.Add(4, "追加行");
        ds.B子.Rows.Add(4, "どうかな?", 12345);
    };

    button2.SetBounds(230, 220, 100, 35);
    button2.Text = "CD=5を追加";
    Controls.Add(button2);
    button2.Click += delegate
    {
        button2.Enabled = false;

        // 行の登録方法、その3
        DataSet1.A親Row rowP = ds.A親.NewA親Row();
        rowP.カラムCD1 = 5;
        rowP.カラム名称 = "新規行";
        ds.A親.AddA親Row(rowP);
        DataSet1.B子Row rowC = ds.B子.NewB子Row();
        rowC.カラムCD1 = 5;
        rowC.カラム名称 = "NewRow";
        rowC.カラム数量 = 987;
        ds.B子.AddB子Row(rowC);
    };
}

引用返信 編集キー/
■14587 / inTopicNo.5)  Re[2]: リレーション子Tableへの新行追加方法について
□投稿者/ 富田 (3回)-(2008/02/22(Fri) 13:20:59)
No14586 (魔界の仮面弁士 さん) に返信
返答ありがとうございます。
リレーションはXSDにて設定しております。

下記がリレーションシップの概要です。
親テーブル    子テーブル
親A        子B


キー列      外部キー列
カラムCD1     カラムCD1

作成する制約の選択
リレーションと外部キー制約の両方

UpdateRuleの設定 None
ルールの削除  None
AcceptRejectRuleの設定  None


下記がテーブルへの追加です。
親A.rows[i][カラムCD1] = キー
親A.rows[i][カラム名称] = 新規

子B.rows[c][カラムCD1] = 親A.rows[i][カラムCD1]

ぐだぐだな説明な感じがします。
申し訳ありません。 
引用返信 編集キー/
■14590 / inTopicNo.6)  Re[1]: リレーション子Tableへの新行追加方法について
□投稿者/ 魔界の仮面弁士 (649回)-(2008/02/22(Fri) 13:27:55)
No14582 (富田 さん) に返信
> A親のデータ1件に対し、B子のデータn件が紐付く関係です。
カラムCD1 というキーで繋がっているのですよね?
定義を見る限り、B子側は0〜n件ではなく、0〜1件に見えるのですが…。

実はB子は「カラムCD2」を持っていて、カラムCD1とカラムCD2で、B子の主キーを成しているのでしょうか?
とりあえず、その前提で回答しなおすと、登録処理は、
ds.A親.Rows.Add(9 "追加行");
ds.B子.Rows.Add(9, 1, "4-1", 111);
ds.B子.Rows.Add(9, 2, "4-2", 222);
ds.B子.Rows.Add(9, 3, "4-3", 333);
であるとか、
DataSet1.A親Row rowP = ds.A親.AddA親Row(10, "10");
ds.B子.AddB子Row(rowP, 1, "10-1", 111);
ds.B子.AddB子Row(rowP, 2, "10-2", 222);
ds.B子.AddB子Row(rowP, 3, "10-2", 333);
といった感じでできますね。


> その際、B子にA親のカラムCD1の値を入れたいのですが、(※B子.rows[i][カラムCD1] = A親.rows[c][カラムCD1]としてます)
B子.rows[i] という事は、その行はすでに B子に登録済みなのですよね。
登録後に、カラムCD1 の値をつけなおしたい、という意味のようなので、

ds.B子.AddB子Row(ds.A親.AddA親Row(1, "あああ"), 10, "アアア", 123);
ds.B子.AddB子Row(ds.A親.AddA親Row(2, "いいい"), 20, "イイイ", 456);
ds.B子.AddB子Row(ds.A親.AddA親Row(3, "ううう"), 10, "ウウウ", 789);

ds.B子[1].カラムCD1 = ds.A親[0].カラムCD1;

ds.EnforceConstraints = false;
ds.B子[2].カラムCD1 = ds.A親[0].カラムCD1;
ds.B子[0].カラムCD2 = 30;
ds.EnforceConstraints = true;

のようなコードを書いてみましたが、
> FK_A親_A子_カラムCD1には、A親のカラムCD1の値が必要です等のメッセージと共に、
というエラーにはなりませんでした。
具体的なコードを提示してもらえますか?
引用返信 編集キー/
■14592 / inTopicNo.7)  Re[3]: リレーション子Tableへの新行追加方法について
□投稿者/ 魔界の仮面弁士 (650回)-(2008/02/22(Fri) 13:50:15)
No14587 (富田 さん) に返信
> リレーションはXSDにて設定しております。
テーブル定義は、(No14590ではなく)No14582,No14586 の定義で良いのですね?

> 作成する制約の選択
> リレーションと外部キー制約の両方
> UpdateRuleの設定 None
> ルールの削除  None
> AcceptRejectRuleの設定  None

私の No14586 の XSD とは、この部分が異なっていたので合わせてみましたが、やはり再現しません。
再現可能なコードがあれば、提示していただけないでしょうか。


> 下記がテーブルへの追加です。
> 親A.rows[i][カラムCD1] = キー
> 親A.rows[i][カラム名称] = 新規
> 子B.rows[c][カラムCD1] = 親A.rows[i][カラムCD1]
「値をセットした DataRow」を登録するのでは無く、
「空の DataRow をとりあえず登録してから、値を設定する」という手法にしているのですね。

A親 では無く親A になっていたり、Rows ではなく rows だったり、行末セミコロンが
抜けていたりと、実際のコードとは別物を提示されているような悪い予感がするのですが、
無理矢理そのコードに合わせるなら、こんな感じですかね。(やはり、エラーが再現しません)

ds = new DataSet1();
ds.EnforceConstraints = false;
ds.A親.Rows.Add();
ds.B子.Rows.Add();

DataTable 親A = ds.A親;
DataTable 子B = ds.B子;
int i = 0, c = 0;
int キー = 100;
string 新規 = "新規";
string カラムCD1 = "カラムCD1";
string カラム名称 = "カラム名称";

// ==> ここから、No14587 のコード
親A.Rows[i][カラムCD1] = キー;
親A.Rows[i][カラム名称] = 新規;
子B.Rows[c][カラムCD1] = 親A.Rows[i][カラムCD1];
// <== ここまで、No14587 のコード

ds.EnforceConstraints = true;
引用返信 編集キー/
■14593 / inTopicNo.8)  Re[3]: リレーション子Tableへの新行追加方法について
□投稿者/ 富田 (4回)-(2008/02/22(Fri) 14:01:10)
皆様、回答ありがとうございます。
魔界の仮面弁士様の要望にお答えしようとして、
ソースを元の状態(いろいろ実験していたので)にし、
リレーションも元の状態にしようとアレコレしていたら、
正常の動作となりました。

ただ、エラーとなっていた原因は不明なままです。

長い間、私のために時間をとらせてしまい、申し訳なく思っております。
またあ、感謝しております。
一応、解決にしときます。
(何故、エラーになったかわからずに、すごい気持ち悪いですが・・)
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -