- PR -

DataView を利用した出力レコード数の制御について

1
投稿者投稿内容
takeyan
会議室デビュー日: 2002/10/02
投稿数: 8
お住まい・勤務地: 東京
投稿日時: 2004-03-02 03:12
初めまして。

現在、Windows 2000 + ASP.NET+IE6.0 + MS-SQLの環境で
Webアプリの開発をしております。VS.NET2003を利用しています。

今回やりたい事は、
1.ネストした Repeater コントロールで2階層のデータを表示する事
2.親となるテーブルのレコードは、順番がランダムで表示される事
3.親となるテーブルのレコードが、特定のキーで絞り込まれている事
4.親となるテーブルの出力レコード数を制御する事
の4つとなります。

1については、
「リピータの中にリピータは作成できますか?」
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=2377&forum=7
というスレッドや、ここから移動できるMSのページを参考にして実現できました。

2については、
SQLからDataTableを作成するときに、ランダム値を入れるための列を1列用意し、
(Select *, 1 as random_id from data_table という形でSelectしました)
上記でいうrandom_idにプログラム中でRandam値を格納し、
DataViewコントロールを用いてSortする事で実現できました。

3については、
2の結果をDataView コントロールのRowFilterを利用して実現できました。

今悩んでいるのが、4番目、出力行の制御となります。
DataTableに格納するタイミングでSQLコマンドで「Top n」等を行い、
取得するレコードを減らす事も考えましたが、それでは、1が実現できませんでした。

DataViewコントロールでなくても構わないのですが、
上記4番を行う方法をご存じの方、いらっしゃいませんでしょうか。
ご教授願えれば幸いです。

宜しくお願い致します。


[ メッセージ編集済み 編集者: takeyan 編集日時 2004-03-02 03:13 ]
ゆうじゅん
ぬし
会議室デビュー日: 2004/01/16
投稿数: 347
投稿日時: 2004-03-02 09:54
SqlDataAdapterでFillするときに読み込み件数が設定できます。
takeyan
会議室デビュー日: 2002/10/02
投稿数: 8
お住まい・勤務地: 東京
投稿日時: 2004-03-02 11:21
書き込みありがとうございます。

SqlDataAdapterでFillするときに、読み込み件数を指定しますと
確かに親Tableに指定された行数でDBからレコードを格納できるかと思います。

ただ、親のDataTableを作成するときにFillで行数の指定を行い、
子のDataTableもFillで作成するときに
親のDataTableTableに存在するレコードとリレーションが
張られたレコードのみを子のDataTableに格納するようにしないと、
最初に記述した1のタイミングで下記のようなエラーが発生してしまいます。


********************************************************
対応する親の値が指定されてない値があるため、この制約を有効にできません。

説明 : 現在の Web 要求を実行中に、ハンドルされていない例外が
発生しました。エラーに関する詳細および例外の発生場所については、
スタック トレースを参照してください。

例外の詳細: System.ArgumentException: 対応する親の値が
指定されてない値があるため、この制約を有効にできません。
対応する親の値が指定されてない値があるため、この制約を有効にできません。

********************************************************

ネストしたRepeaterを利用する場合に限らないでしょうが、
リレーションを張っている以上、子のDataTableは、
親のDataTableと整合性がないといけないので、
親のDataTableを作成した後に、子のDataTableを作成するSQLコマンドを
親のTable上のデータに対応して動的に作成するといった方法が
この問題の解決策となりますでしょうか?
(ただ、仮定であってまだ試していませんので
実装に関してはこれから試してみようと思います)

現在は実際のDB上のテーブルから、そのまま親のDataTableも子のDataTableも取得し、
表示する直前のタイミングでDataViewを利用して内容を絞り込んでいましたので、
同じタイミングで、表示する親のレコード数を指定できないかと
考えたのですが、このような方法はありませんでしょうか?
ゆうじゅん
ぬし
会議室デビュー日: 2004/01/16
投稿数: 347
投稿日時: 2004-03-02 11:23
>DataTableに格納するタイミングでSQLコマンドで「Top n」等を行い、
>取得するレコードを減らす事も考えましたが、それでは、1が実現できませんでした。

試しましたがわたしのやり方でもエラーがでますね。申し訳ない。
ちなみにエラーは「外部キー制約違反」ですか?

少し強引ですがDataTableに連番列を追加することで対応できそうです。

コード:

// 連番の列を親テーブルに追加
DataColumn myColumn = new DataColumn();
myColumn.DataType = System.Type.GetType("System.Int32");
myColumn.AutoIncrement = true;
myColumn.AutoIncrementSeed = 1;
myColumn.AutoIncrementStep = 1;
myColumn.ColumnName = "ID";
ds.Table1.Columns.Add( myColumn );

// 親、子テーブルを読み込む
sqlDataAdapter1.Fill( ds );
sqlDataAdapter2.Fill( ds );

// ビューを作成して連番で絞込み
DataView view = ds.Table1.DefaultView;
view.RowFilter = "ID < 6"; // 5件表示



(追加)
書き込みしている間に返答が・・・。
やっぱり「外部キー制約違反」だったみたいですね


[ メッセージ編集済み 編集者: ゆうじゅん 編集日時 2004-03-02 11:26 ]
NAL-6295
ぬし
会議室デビュー日: 2003/01/26
投稿数: 966
お住まい・勤務地: 東京
投稿日時: 2004-03-02 11:31
NAL-6295です。

ItemDataBoundイベント内で表示したい行数分カウントして、それを超えたら
引数で渡ってくる

e.Item.visible = false

でも、とりあえずは実現できますけどね・・・。

#あくまでとりあえず。
#修正:イベント名その他

[ メッセージ編集済み 編集者: NAL-6295 編集日時 2004-03-02 11:46 ]
takeyan
会議室デビュー日: 2002/10/02
投稿数: 8
お住まい・勤務地: 東京
投稿日時: 2004-03-02 13:19
>ゆうじゅんさん

ゆうじゅんさんのやり方と同様の内容を試していたのですが、
(DataTableの項目に直接ループで値を格納するというやり方でしたので、
今回のやり方はとても参考になりました。ありがとうございます)
連番の列を親テーブルに追加するタイミングについて質問なのですが、
DataViewを利用して、表示する内容を絞り込んだ後に
(3の親となるテーブルのレコードを、特定のキーで絞り込む処理の後)
そのような連番はつけられますでしょうか。

DataViewのRowFilterを利用して絞りこみを行う前に連番をつけますと、
親の中で表示させたいキーが存在するレコードも含めて連番となってしまい、
RowFilterで、キーによる絞込み&列数の絞込みを指定しても
正しく行数が指定できていませんでした。

DataViewのRowFilterを利用した結果を
DataTableに格納できればと思いましたが、
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=9453&forum=7
を参考にしたところ、DataView.Tableでは、
参照しているTableそのものを返しますので、
親のDataTable内にある、欲しいキーを持ったレコードに対して
連番をつけるという事が結局のところ出来ずにいます。
主題とずれるのかもしれませんが、
こちらの方法についてご存知ありませんでしょうか。
DataSetはメモリの中のDBという概念で捉えていましたが、
いろいろ出来るという幻想を持ちすぎなのでしょうか。。。


>NAL-6295さん
確かに、NAL-6295さんのやり方もひとつの解決策ですね。
こちらの方法について、ぜんぜん思いつきませんでした。
ありがとうございます。早速試してみます!
ya
大ベテラン
会議室デビュー日: 2002/05/03
投稿数: 212
投稿日時: 2004-03-02 14:47
引用:

今悩んでいるのが、4番目、出力行の制御となります。
DataTableに格納するタイミングでSQLコマンドで「Top n」等を行い、
取得するレコードを減らす事も考えましたが、それでは、1が実現できませんでした。




リレーション先の Table をFillするときにも、
SELECT * FROM child WHERE ID IN (SELECT TOP n ID FROM parent)
みたいにIDを限定するといいと思うのですが、それでは駄目なのですか?

あるいはもっと簡単にリレーションを張らずに、DataTable.Select()メソッドを使うとか(使えないかな?)。

[ メッセージ編集済み 編集者: ya 編集日時 2004-03-02 14:58 ]
takeyan
会議室デビュー日: 2002/10/02
投稿数: 8
お住まい・勤務地: 東京
投稿日時: 2004-03-02 22:21
>yaさん
すいません、SQLコマンドの勉強不足でした。
SQLポケットリファレンスで「IN」について調べてみました。
これですと、確かにリレーションが張られているもののみを
抜き出せますので、子のDataTableを作る段階で
不整合を発生せず容易に絞り込みが可能なようですね。

この方法と、ゆうじゅんさんのDataTableに連番列を追加する方法を
組み合わせると4も実現できそうです。

NAL-6295さんのItemDataBoundイベントでも
実装出来ることは確認できたのですが、
こちらの方法でも試してみます。

>ゆうじゅんさん、NAL-6295さん、yaさん
本当にありがとうございます!
1

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