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

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

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

Re[4]: DataRow.GetChildRowsの結果の並び順


(過去ログ 133 を表示中)

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

■78449 / inTopicNo.1)  DataRow.GetChildRowsの結果の並び順
  
□投稿者/ あゆ (3回)-(2016/01/14(Thu) 17:47:05)

分類:[.NET 全般] 

こんにちは

DataSetに親テーブルと子テーブルを追加し、
DataRelationを使い、親テーブルと子テーブルの関連付けを行い、
親レコードから子レコードをDataRow.GetChildRowsで
DataRowの配列を取得しています。

そこで気になっているのが、
GetChildRowsで得られる子レコードのDataRow配列の並び順は、
何らかの順で並ぶことが保証されているのでしょうか?

雰囲気的には子テーブルに登録された順のようですが、
子テーブルに対し、追加・削除・PKフィールドの値変更などの操作を行っても、
必ず登録されたレコード順なのか、場合によっては変わることがあるのか
が分かりません。

もし、GetChildRowsで得られるDataRow配列の並びが保証されていない場合、
DataRow配列を特定の並び順で処理したい場合は、
独自にソートするしかないのでしょうか?

お分かりになる方がいらっしゃいましたら、
ご回答よろしくお願いします。
引用返信 編集キー/
■78454 / inTopicNo.2)  Re[1]: DataRow.GetChildRowsの結果の並び順
□投稿者/ ぶなっぷ (67回)-(2016/01/15(Fri) 09:12:55)
いまいちピンときません、実例を挙げて説明してもらえると分かりやすい
かもです。

えーと、たぶんで回答してみますが。

前提条件は、リレーションのはられたテーブルがあって、
主テーブルから外部キーで副テーブルの主キーにつながってると。
で、副テーブル側のデータをソートした状態で取得したいと、
もちろん重複なしで。
そんなところかな?

そうだと仮定するなら、プログラミングでどうにかするのは処理速度的に
不利です。SQLに任せた方が良いです(そのためのDBです)。

主テーブルと副テーブルをJOINして、ソート条件はORDERBYで与えます。
主テーブルの外部キーからのJOINだと、副テーブルのレコードは複数一致
するでしょうから、SELECTの結果表に含めるフィールドは副テーブルの
フィールドのみ(副テーブルの主キーは必須)とし、DISTINCTをかけます。

Oracleなら、DISTINCTの使い方は以下の通り。
  http://www.shift-the-oracle.com/sql/distinct.html

これで、DataSetにはソート済みの結果表が返ってきますので、
自分でソートする必要はありません。

引用返信 編集キー/
■78456 / inTopicNo.3)  Re[2]: DataRow.GetChildRowsの結果の並び順
□投稿者/ あゆ (4回)-(2016/01/15(Fri) 10:16:10)
ぶなっぷ さん

ご回答ありがとうございます。

あいまいな質問になってしまって申し訳ありません。
テストコードを下記に貼り付けますので、
ご確認頂ければと思います。

> 前提条件は、リレーションのはられたテーブルがあって、
> 主テーブルから外部キーで副テーブルの主キーにつながってると。
> で、副テーブル側のデータをソートした状態で取得したいと、
> もちろん重複なしで。
> そんなところかな?

はい。イメージはあっています。

> そうだと仮定するなら、プログラミングでどうにかするのは処理速度的に
> 不利です。SQLに任せた方が良いです(そのためのDBです)。

ここがちょっと違いまして、今回はDBを使用せずに、
上記のことを実現したいと思っています。


下記がテストコードになります。
下の方にある
row.GetChildRows("relationKey")
の戻り値となる DataRow[] の設定順がなんの順なのかが知りたいです。

ここから==============================================================
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication4
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
// 親テーブルを定義
DataTable parentTable = new DataTable();
parentTable.TableName = "parentTable";
parentTable.Columns.Add("Key", typeof(System.Int32));
parentTable.Columns.Add("ParentName", typeof(System.String));
parentTable.PrimaryKey = new DataColumn[] { parentTable.Columns["Key"] };

// 子テーブルを定義
DataTable childTable = new DataTable();
childTable.TableName = "childTable";
childTable.Columns.Add("Key", typeof(System.Int32));
childTable.Columns.Add("SubKey", typeof(System.Int32));
childTable.Columns.Add("ChildName", typeof(System.String));
childTable.PrimaryKey = new DataColumn[] { childTable.Columns["Key"], childTable.Columns["SubKey"] };

// レコードの追加 親レコード1件につき、子レコード20件作成 最終的に 親レコード10件 子レコード200件作成
for (int i = 1; i <= 10; i++)
{
// 親レコード追加
DataRow parentRow = parentTable.NewRow();
parentRow["Key"] = i;
parentRow["ParentName"] = string.Concat("parent name ", i);
parentTable.Rows.Add(parentRow);

// 子レコード追加
for (int j = 1; j <= 20; j++)
{
DataRow childRow = childTable.NewRow();
childRow["Key"] = i;
childRow["SubKey"] = j;
childRow["ChildName"] = string.Concat("child name ", i, " - ", j);
childTable.Rows.Add(childRow);
}
}

// DataSetに親テーブル・子テーブルを追加し、双方のKeyフィールドでリレーションを張る
DataSet tables = new DataSet();
tables.Tables.Add(parentTable);
tables.Tables.Add(childTable);
tables.Relations.Add(new DataRelation("relationKey", parentTable.Columns["Key"], childTable.Columns["Key"]));

// 親テーブル・子テーブルの内容をテキストファイルに書き込み
using (System.IO.StreamWriter writer = new System.IO.StreamWriter(@"D:\Temp\TestDataTable.txt"))
{
foreach (DataRow row in parentTable.Rows)
{
// 親テーブルのレコードをテキストファイルに出力
writer.WriteLine(string.Format("{0} {1}", row["Key"], row["ParentName"]));

// このrow.GetChildRowsで帰ってくる DataRow[] の並び順は??
// 雰囲気的には登録順だけど保証されている??
// 子テーブルに操作(レコードの削除・レコードの追加・PKの変更など)を加えたときも登録順が保証されている?
foreach(DataRow row2 in row.GetChildRows("relationKey")){
// 子テーブルのレコードをテキストファイルに出力
writer.WriteLine(string.Format("\t{0} {1} {2}", row2["Key"], row2["SubKey"], row2["ChildName"]));
}
writer.WriteLine();
}
}
}
}
}
ここまで==============================================================

以上です。
よろしくお願いします。
引用返信 編集キー/
■78457 / inTopicNo.4)  Re[3]: DataRow.GetChildRowsの結果の並び順
□投稿者/ ぽぴ王子 (35回)-(2016/01/15(Fri) 10:57:16)
ぽぴ王子 さんの Web サイト
No78456 (あゆ さん) に返信

今回は DataSet 上での DataTable 間のリレーションという話ですね。
なので、DB も SQL も無関係かと思います。

> GetChildRowsで得られる子レコードのDataRow配列の並び順は、
> 何らかの順で並ぶことが保証されているのでしょうか?

MSDN を見る限りでも、特に明記されているわけではないようです。
となると、保証はされていないと考えるのが妥当でしょうね。
実装上登録された順に並んでいるが、それも保証されたものではないと。

> もし、GetChildRowsで得られるDataRow配列の並びが保証されていない場合、
> DataRow配列を特定の並び順で処理したい場合は、
> 独自にソートするしかないのでしょうか?

自分は GetChildRows を使用したことがないのですが、やはり
独自にソートするしかなさそうです。

Framework のバージョンが書かれていないのでわかりませんが、3.5 以上であれば
こんな書き方もできるかと思います。

DataRow[] childRows = row.GetChildRows("relationKey").OrderBy(x => x["Key"]).ToArray();

あとはこんな感じでしょうか。

IComparer compareClass = new CompareClass();
Array.Sort(row.GetChildRows("relationKey"), compareClass);

public class CompareClass : IComparer
{
    public int Compare(object x, object y)
    {
        DataRow s = (DataRow)x;
        DataRow d = (DataRow)y;

        return (int)s["Key"] - (int)d["Key"];
    }
}

ちゃんとテストをしていないので動く保証はできませんが、結局のところ自前でソートする
必要がありそうだ、ということで。

※ソースコードを投稿するときは、投稿モードを「図表モード」にしたほうがよいです。

引用返信 編集キー/
■78458 / inTopicNo.5)  Re[3]: DataRow.GetChildRowsの結果の並び順
□投稿者/ shu (795回)-(2016/01/15(Fri) 11:04:41)
No78456 (あゆ さん) に返信

たぶん追加順だと思いますが、希望する順番があるのならソートを行うべきです。
引用返信 編集キー/
■78459 / inTopicNo.6)  Re[4]: DataRow.GetChildRowsの結果の並び順
□投稿者/ あゆ (5回)-(2016/01/15(Fri) 11:48:42)
ぽぴ王子 さん

ご回答ありがとうございます。

>>GetChildRowsで得られる子レコードのDataRow配列の並び順は、
>>何らかの順で並ぶことが保証されているのでしょうか?
>
> MSDN を見る限りでも、特に明記されているわけではないようです。
> となると、保証はされていないと考えるのが妥当でしょうね。
> 実装上登録された順に並んでいるが、それも保証されたものではないと。

そうなんです。。。
私も確認したつもりなのですが、DataRowの配列が返ってくるとしか情報が得られず、
実際試してみると、登録順のようだけど、確証が持てないという状態でしたが、
「保証されたものではない」と思うようにします。

> Framework のバージョンが書かれていないのでわかりませんが、3.5 以上であれば
> こんな書き方もできるかと思います。
>
> DataRow[] childRows = row.GetChildRows("relationKey").OrderBy(x => x["Key"]).ToArray();
>
> あとはこんな感じでしょうか。
>
> IComparer compareClass = new CompareClass();
> Array.Sort(row.GetChildRows("relationKey"), compareClass);
>
> public class CompareClass : IComparer
> {
> public int Compare(object x, object y)
> {
> DataRow s = (DataRow)x;
> DataRow d = (DataRow)y;
>
> return (int)s["Key"] - (int)d["Key"];
> }
> }

コードサンプル、非常に助かります!!
参考にさせていだたきます。

それと、Frameworkのバージョン書き忘れてました。すいません。
今更ですが 4.5で実装しています。

> ちゃんとテストをしていないので動く保証はできませんが、結局のところ自前でソートする
> 必要がありそうだ、ということで。

了解しました!

> ※ソースコードを投稿するときは、投稿モードを「図表モード」にしたほうがよいです。

「図表モード」ってなんだろなぁ…と思ってましたけど、
このような用途に使えるんですね。
こちらも勉強になりました。

以上です。
ありがとうございました。
解決済み
引用返信 編集キー/
■78460 / inTopicNo.7)  Re[4]: DataRow.GetChildRowsの結果の並び順
□投稿者/ あゆ (6回)-(2016/01/15(Fri) 11:53:51)
shuさん

ご回答ありがとうございます。

> たぶん追加順だと思いますが、希望する順番があるのならソートを行うべきです。

そうなんです。
たぶん追加順なんです。。。

この「たぶん」がひっかかってました。
希望する順番は追加順のままなのですが、
その追加順が保証されているのか分からず、不安でした。

不安なまま実装を進めるのは気持ちが悪いので、
ソートするようにします。

以上です。
解決済み
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -