tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルLINQtoSQLでのSELECT順
記事No7691
投稿日: 2008/06/13(Fri) 11:23
投稿者ひぃ
こんにちわ。宜しくお願い致します。

現在の開発環境は、VB.NET2008+SQLServer2005です。


AccessVBAで作成されていたプログラムを、
完全新規で.NET版にシステムリプレイス中なのですが、
LINQtoSQLを利用して開発を行っております。

現在悩んでおりますのは、LINQtoSQLのSELECT順についてです。

フォーム上にDataGridViewを配置(データソース無し)し、
複数のテーブルからデータを結合、必要なデータのみをDataGridViewに表示させる。

というところまでは出来たのですが、
LINQtoSQLにて指定したSELECT順の通りにDataGridViewに表示されません。


現在のソースを抜粋致しました。

    Private Sub frmTest_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim dtc = New dcMeisaiCheck

        Dim var = From SitenMei In dtc.SitenTbl, KaMei In dtc.KaTbl, test In dtc.KaTbl _
                   Where SitenMei.SitenCD = KaMei.SitenCD _
                   Order By SitenMei.SitenCD , KaMei.KaCD_
                   Select SitenMei.SitenName, SitenMei.SitenCD , KaMei.KaName, KaMei.KaCD

        Me.DataGridView1.DataSource = var

    End Sub

という感じでSELECTにて取得順序を指定していますが、
実際にフォームで表示させてみると、
SitenMei.SitenCD, SitenMei.SitenName, KaMei.KaCD, KaMei.KaName
となってしまっています。

いろいろ調べてみたのですが、
LINQtoSQLにて生成されるSQLでは指定した順序で取得してきているようです。
DataSourceに直接放り込むのが良くないのか?と思い、
ソースにてBindingSourceを用意して放り込んでみましたが、
BindingSourceに入った時点で順序がおかしくなっているようです。

※クイックウォッチで見てみると、BindingSourceの中のDataSourceの中、
 さらに結果の中の各レコードの情報が見えましたが、
 それの順序がSELECT順になっていないようです。
 (SitenMei.SitenCD, SitenMei.SitenName, KaMei.KaCD, KaMei.KaNameになっていました)

何か良い方法はないものでしょうか。。。

[ツリー表示へ]
タイトルやはり無理なのでしょうか
記事No7698
投稿日: 2008/06/17(Tue) 09:07
投稿者ひぃ
とりあえず、別の掲示板でも聞いてみようと思います。
もし解決したらこちらにもご報告させて頂きます。

[ツリー表示へ]
タイトルRe: やはり無理なのでしょうか
記事No7700
投稿日: 2008/06/17(Tue) 14:57
投稿者ゆうき
ゆうきです。

> とりあえず、別の掲示板でも聞いてみようと思います。
それはマルチポストになるのでは?

[ツリー表示へ]
タイトルRe^2: やはり無理なのでしょうか
記事No7702
投稿日: 2008/06/17(Tue) 17:07
投稿者ひぃ
> ゆうきです。
>
> > とりあえず、別の掲示板でも聞いてみようと思います。
> それはマルチポストになるのでは?

    別掲示板の方には最初にマルチになっている事をお断りしています。
  両方の掲示板に結果報告は返答致しました。
  それでも何か問題がありますか?

[ツリー表示へ]
タイトル一先ず解決しました。
記事No7699
投稿日: 2008/06/17(Tue) 14:56
投稿者ひぃ
別掲示板にてヒントを頂いて一先ずの解決が出来ましたのでご報告致します。

別掲示板にて頂いたヒントは下記二点。
・DataGridView の Column の DataPropertyName を適切に設定する。
・匿名型の要素に名前をつける


お客さんの依頼の重要項目に、
「後々にカスタマイズが発生した場合、
 開発者でなくても簡単にカスタマイズ出来るような作りにして欲しい」
というのがありましたので、
今回は、Stringの配列を利用して、そこだけ変更すればOKなように作ってみました。

dim strColNM() As String = { "支店名", "支店コード", "課名", "課コード"}

For intCnt = 0 to (strColNM.Count - 1)
    Me.DataGridView.Colmuns.Add( strColNM(intCnt), strColNM(intCnt))
    Me.DataGridView.Colmuns(intCnt).DataPropertyName = strColNM(intCnt)
Next

Dim dtc As New dcTestCheck

Dim var = From SitenMei In dtc.SitenTbl, KaMei In dtc.KaTbl _
          Where SitenMei.SitenCD = KaMei.SitenCD _
          Order By SitenMei.SitenCD , KaMei.KaCD_
          Select 支店名 = SitenMei.SitenName _
               , 支店コード = SitenMei.SitenCD _
               , 課名 = KaMei.KaName _
               , 課コード = KaMei.KaCD

Me.DataGridView.DataSource = var

フィールド名を配列に入れないといけないのは面倒ですが、
なんとか綺麗に収まったかな?と思っています。
クエリデータにフィールド名を特定出来るようなプロパティがあれば(あるのかも知れませんが)
配列も無しに出来るような気がします。

一先ずやりたい事は出来ましたので解決とさせていただきます。
ありがとうございました。

[ツリー表示へ]
タイトルRe: 一先ず解決しました。
記事No7703
投稿日: 2008/06/18(Wed) 12:41
投稿者癒耶
マルチポストお断りって書いてありますよ。
それに事前にマルチポストをすると連絡したという事ですが
もう一つの掲示板のURLもわからない以上、意味がないかと。

[ツリー表示へ]
タイトルRe: 一先ず解決しました。
記事No7704
投稿日: 2008/06/18(Wed) 17:01
投稿者よねKEN
> 別掲示板にてヒントを頂いて一先ずの解決が出来ましたのでご報告致します。

こちらのやりとりですね。
http://hpcgi1.nifty.com/MADIA/vbnet/wwwlng.cgi?print+200806/08060160.txt

他の方からマルチポストについてご意見が上がっているようですが、
私は以下の理由から問題ないと思います。

1. 質問を投稿されてからしばらく様子を見たがコメントが付かなかった。
  当初、私はこの質問は読みましたが、LINQはまだあまり使っていなくて
  回答できることがなかったので、スルーしてました。回答に必要な情報は
  揃っていたと思いますので、質問文には特に問題なかったと思います。

2. 別の掲示板で再質問をされる旨をこちらでコメントされて一区切り付けた。

3. 別所で質問し解決できたので、結果内容を報告をされた。

(4. 別所で質問される際も、既に質問をしている掲示板があるが、
  コメントが付かなかった点について言及している。)

ツッコミを入れるとしたら、各掲示板にそれぞれのURLを記載しておきましょう、
というくらいでしょうか。

マルチポストについて指摘されている方は、こちらの掲示板では、
基本的にはマルチポストを禁止されている点をみてのご指摘かと思いますが、
「初めにお読み下さい」で言及されていますが、今回の場合はマルチポストには
当たらないと思います。

「初めにお読み下さい」より引用。
>>少なくても、最初に書き込んだ掲示板で2〜3日は回答を待ちましょう。又、書き込んだすべての掲示板に、返信・解決報告は必ずして下さい。

OKですよね。

[ツリー表示へ]
タイトルRe^2: 一先ず解決しました。
記事No7705
投稿日: 2008/06/18(Wed) 18:09
投稿者るしぇ
マルチポストの定義は複数掲示板への投稿なんだから、
>VB初心者友の会等他サイトに投稿され、さらに、
>こちらにも投稿されるような事は一般的に(マルチポストと呼ばれ)
この部分で判断すべきで、マルチポストで無くなるわけではないでしょう。

問題は管理人さんが投稿フォームの上部に
『マルチポストはお断りします』といった内容を書いちゃってることで、
そこまで書くなら「初めにお読み下さい」の条件付で許すような表現は
改めた方がいいと思います。

>「初めにお読み下さい」より引用。
>>>少なくても、最初に書き込んだ掲示板で2〜3日は回答を待ちましょう。
>>>又、書き込んだすべての掲示板に、返信・解決報告は必ずして下さい。
『少なくても』ってのは最低限ってことで、守ってもOKではないとボクは
解釈します。

ま、管理人さんの対応待ちでしょうか。

# 『少なくても』って使うものなの?国語辞典に載ってるのは『少なくとも』
# だと思うけど。

[追記]
ボクがマルチポストお断りのサイトを利用した後、掲示板を移動したい場合は
  ・利用させてもらった御礼
  ・移動する理由(回答を得られなかった等)
  ・移動先のアドレス
を書いてスレッドを閉じますね。
全ての掲示板に結果を報告するとかいうのはマルチポストありきの話に
なるし、ローカルルールだよ。

[ツリー表示へ]
タイトルRe^3: 一先ず解決しました。
記事No7706
投稿日: 2008/06/18(Wed) 18:34
投稿者やじゅ

一般用掲示板に意見・要望がありますので、
そちらに記述されても良いかと思います。

[ツリー表示へ]
タイトルRe^3: 一先ず解決しました。
記事No7707
投稿日: 2008/06/18(Wed) 19:10
投稿者花ちゃん
私は、マルチポストはマナー違反と思っております。
たばこのポイ捨てを注意され拾えば問題ないかと言えばそうではないはず、それが
許されるなら、万引きして見つかれば金を払うなり品物を返せば良いと言うような
事にもつながります。
ただし、マルチポスト程度の事ですから、マナー違反をした事を承知で他のサイトへ
投稿される場合は、それなりの礼を尽くされるなら容認しましょうと言う事を書いて
いるつもりです。

その人が行った行為はリセットはできないかと思います。従って、投稿者の何々を
したから、マルチポストをしても問題ないとは思えません。
レスは、していなくても質問に対して調べていた人もあるでしょうし、現にこのような
投稿があるのですから。

私の思いは、初めにお読みくださいに書いているようにマナーを守って下さいと言って
いるだけです。

マナーを守れず、マルチポストするなら最低限の礼は尽くして下さいと言う事です。

[ツリー表示へ]
タイトル謝罪 と その後判明した事
記事No7728
投稿日: 2008/06/24(Tue) 14:59
投稿者ひぃ
何より先にまずお詫びさせて頂ければと思います。
賛否両論はあるようですが、URLを記述しなかった点や、
こちらでの決まりに違反していた事を謝罪致します。


さて、今回、書き込みさせて頂きましたのには理由があります。
前回書き込んだ「一先ず解決しました」ではまだ解決出来ていなかったからです。
(自分としては解決出来たつもりでいましたが、テストを実施していたら不具合が見つかりました)
完全解決ではありませんが、逃げ道を見つけましたのでご報告させて頂きます。
(少々長くなりますのでご興味がある方のみお読み頂くか、LINQ開発する時の参考にして頂ければ幸いです)


前回書き込みさせて頂いたソースでは、DataPropertyNameを設定すれば可能
というような感じになっていましたが、それだけでは実現出来ませんでした。
DataPropertyNameを正しく設定すれば、その行に値は入るのですが、
当初の問題であった、「SELECT順の通りに並ばない」が実現出来ていませんでした。
(フィールド数が多かったので、少し確認して「出来た」と思い違いしていました)
当初質問させて頂いていた状態での結果と、
DataPropertyNameを設定してからの結果では並び順は少し変わっていましたが、
やはりこちらが指定した通りのSELECT順にはなっていませんでした。

例えば、以下のような2つのテーブルがあったとします。
テーブル名:Siten_Table AS Siten
フィールド名:A_SitenCD,B_SitenMei,C_SitenChoCD,D_SitenChoMei
テーブル名:Ka_Table AS Ka
フィールド名:A_SitenCD_Ka,B_KaCD,C_KaMei,D_KaChoCD,E_KaChoMei
(並び順がどうなるか分かりやすいように頭をABCにしています)

このテーブルをLINQの結合で取得したとします。
当初の状態(DataPropertyNameに設定なし)で実行すると、
実際にDataGridViewに表示される順は、
Siten.A_SitenCD, Ka.A_SitenCD_Ka, Ka.B_KaCD, Siten.B_SitenMei,
Ka.C_KaMei, Siten.C_SitenChoCD, Ka.D_KaChoCD, Siten.D_SitenChoMei, Ka.E_KaChoMei
というように、完全にABC順に並んでしまいます。
(実際にこういうテーブルを用意して試したわけではありませんが、
 私が使っているテーブルでは完全ABC順となりました)

では、DataPropertyNameに設定有で実行すると、
実際にDataGridViewに表示される順は、
Siten.A_SitenCD, Siten.B_SitenMei, Siten.C_SitenChoCD, Siten.D_SitenChoMei,
Ka.A_SitenCD_Ka,Ka.B_KaCD,C_KaMei,Ka.D_KaChoCD,Ka.E_KaChoMei
というように、テーブル単位でABC順に並んでいました。
恐らく、結合順序によりこの逆の状態にもなるのではないかと思います。

原因を調べる為にステップ実行でいろんなプロパティを見ていたのですが、
データソース=LINQ結果が行われた瞬間に変更される値を見つけました。
DataGridViewが所有する「DisplayIndex」というプロパティでした。
「一先ず解決しました」で記述しましたソース

dim strColNM() As String = { "支店名", "支店コード", "課名", "課コード"}

For intCnt = 0 to (strColNM.Count - 1)
     Me.DataGridView.Colmuns.Add( strColNM(intCnt), strColNM(intCnt))
     Me.DataGridView.Colmuns(intCnt).DataPropertyName = strColNM(intCnt)
Next

Dim dtc As New dcTestCheck

Dim var = From SitenMei In dtc.SitenTbl, KaMei In dtc.KaTbl _
           Where SitenMei.SitenCD = KaMei.SitenCD _
           Order By SitenMei.SitenCD , KaMei.KaCD_
           Select 支店名 = SitenMei.SitenName _
                , 支店コード = SitenMei.SitenCD _
                , 課名 = KaMei.KaName _
                , 課コード = KaMei.KaCD

Me.DataGridView.DataSource = var

↑の「Me.DataGridView.DataSource = var」が実行されるまでの
「DisplayIndex」はColmuns.Addした順になっているのですが、
「Me.DataGridView.DataSource = var」が実行されると、
「DisplayIndex」の中身が変更される。という現象が起きます。

おそらくLINQの仕様なのではないかと思いますが、
LINQの結合で取得した結果(データベース クエリという名前らしいです)
の中身が既にABC順となっていました。
それをDataGridViewのデータソースに入れると、順番がバラバラとなり、
DataPropertyNameを設定していない場合は完全ABC順
DataPropertyNameを設定した場合でもテーブル単位でABC順
に並び変わってしまうようです。

これを回避するには、「DisplayIndex」を当てなおすしかありません。
(もしくはLINQのクラスに必要なフィールドを順番通りに抜き出したクエリ用のClassを作成して、
 それをデータソースとしてDataGridとして表示させる。でしょうか?
 試していないので出来るかどうかはわかりませんが)
私は、お客様の依頼により、
「デザイナで全部出来るならデザイナでやって欲しいが、
 それが無理ならば、逆にデザイナはあまり使わず、
 ソースでここだけ直せば大丈夫。という状態にして欲しい」
という事でしたので、DisplayIndexを当て直す事にしました。

以下のようなソースになります。

dim strColNM(,) As String = {{0,"支店名"}, {1,"支店コード"}, {2,"課名"}, {3,"課コード"}}

For intCnt = 0 to strColNM.GetUpperBound(0)
     Me.DataGridView.Colmuns.Add( strColNM(intCnt,1), strColNM(intCnt,1))
     Me.DataGridView.Colmuns(intCnt).DataPropertyName = strColNM(intCnt,1)
Next

Dim dtc As New dcTestCheck

Dim var = From SitenMei In dtc.SitenTbl, KaMei In dtc.KaTbl _
           Where SitenMei.SitenCD = KaMei.SitenCD _
           Order By SitenMei.SitenCD , KaMei.KaCD_
           Select 支店名 = SitenMei.SitenName _
                , 支店コード = SitenMei.SitenCD _
                , 課名 = KaMei.KaName _
                , 課コード = KaMei.KaCD

Me.DataGridView.DataSource = var

'データソースに入れた後、DisplayIndexを当て直す(LINQ仕様回避)
For intX = 0 to (Me.DataGridView.ColmunCount - 1)
    For intY = 0 to strColNM.GetUpperBound(0)
        If Me.DataGridView.Colmuns(intX).Name = strColNM(intY,1) Then
            Me.DataGridView.Colmuns(intX).DisplayIndex = strConNM(intY,0)
        End IF
    Next intY
Next intX


かなり逃げなソースですが、
配列に指定した数値通りの順に行を並べる事が出来ました。

長々と書き込み申し訳ありませんでした。
どなたかの参考になれば幸いです。

[ツリー表示へ]