none
VB.NET DataSetのテーブルを、自前のクラスで編集、、、 RRS feed

  • 質問

  • 回答をお願いする人に、質問内容が伝わっていない、というご指摘、本当にすいません。

    初心者だから免罪符、とは思っていませんが、、、

    もう一度、整理しました。

    先ず、VS2010、VB.NETで、GridViewを使った画面を作っています。

    GridViewに表示するデータはSqlserverのストアードプロシージャから取得します。

    取得したデータをそのままGridViewにバインドさせるのではなく、一部のカラムを編集する必要があります。

    (カラム数が増えるわけではありません)業務アプリなどでは、よくあるパターンだと思いますが、、、

    そこで、自前のクラスを作って、そのクラスの中で表示内容を編集して、その結果を受け取り、GridViewにバインドさせる、という構造にしたいと思っています。

    ここからが、本題になると思いますが、クラスの中では、問題なくデータは取得できていて、Datasetに格納されている事も確認できています。なので、問題は、そのDatasetをそっくり、プロパティとしてセットしてあげる事ができれば良い、そう考えました。

    理屈では問題なさそうなのですが、、データを取得したDatasetをクラスのプロパティにセットする事が出来なくて困っています。

    つまり、イメージ的には、、、『プロパティ=Dataset』みたいな事をしたい、という事です。

    クラスのメンバー、プロパティは、以下のようにコーディングしています。

    Private _tblSchedule As dsNaPo.rsGetScheduleFulDataTable

    Property TblSchedule As dsNaPo.rsGetScheduleFulDataTable

            Get
                Return _tblSchedule
            End Get

            Set(value As dsNaPo.rsGetScheduleFulDataTable)
                _tblSchedule = value
            End Set

    End Property

    この状態で、、、

    Dim ds As New DataSet()

    dtAdapter.Fill(ds, "TABLE_SCHEDULE")→ Fillメソッドでスケジュールテーブルへ取り込みは成功しています。

    なので、繰り返しになりますが、datasetのTABLE_SCHEDULEの内容を、そっくり、一発で、_tblScheduleにセットしてできれば、問題ないのですが、、、つまり『_tblSchedule=TABLE_SCHEDULE』という事をしたのですが、さっぱりうまく行きません。。

    そもそも、こういう事ができないのか、それとも、何か、基本的な考え方が間違っているのか、ちょっと見当が付きません、、、

    オブジェクト指向の基礎がなっていない、Datasetの事も超初心者というレベル故、立ち往生しております。

    すいません、お助けください。

    よろしくお願いします。



    • 編集済み 梵天丸 2014年9月21日 10:29
    2014年9月21日 8:49

すべての返信

  • 掲示板に書いてあること以外は何も知り得ない回答者に、どのような情報を提供すればあなたの開発環境・何を作っているか・どのようなシナリオかなどを的確に理解してもらえ、タイムリーに的確な回答をもらえるか、よく考えて質問していただけませんか。

    質問するにもそれなりのスキルは必要です。初心者だからというのは免罪符にはなりません。


    • 編集済み SurferOnWww 2014年9月21日 9:24 誤記訂正
    2014年9月21日 9:24
  • DataTable のみ 1 つの親クラス、不明な型の空のテーブルを作成するために使用します。あなたの"dsNaPo.rsGetScheduleFulDataTable"クラスに直接アクセスできる、クラスは厳密に型指定されたデータ テーブル (厳密に型指定されたデータセット データセットをドラッグすることによって) とテーブルのフィールドの value プロパティを設定します。だからちょうど DataTable の代わりに"dsNaPo.rsGetScheduleFulDataTable"を使用する必要があります。

    ASP.NET Forum
    Other Discussion Forums
    FreeRice Donate
    Issues to report
    Free Tech Books Search and Download

    • 回答の候補に設定 Jitta 2014年9月24日 0:20
    • 回答としてマーク 星 睦美 2014年10月14日 2:33
    2014年9月21日 9:24
  • > 取得したデータをそのままGridViewにバインドさせるのではなく、一部のカラムを編集する必要があります。

    それを具体的にどうしたいのか書いてください(あくまで具体的に)。それによっては、あなたが考えているよりもっと簡単にかつスマートにできるかもしれません。

    あと、最初の質問にレスがついたら、それ以降質問を書き直すのは止めてください。後から見る人にとってわけが分からなくなります。

    ここは、質問者さん専用の Q&A サイトではなくて、技術者・開発者同士の情報交換の場所と考えていただけると幸いです。


    • 編集済み SurferOnWww 2014年9月21日 12:24 誤字訂正
    2014年9月21日 12:22
  • 私専用のサイトだなんて、思ってもいません。

    そんな考えは、一切ありません。

    本件は、これから先、汎用的に使える技術を知りたくて、ご存知の方が、いらっしゃればご教授いただきたい、そう思っただけです。

    質問を投稿する事がいけないことならこの質問は辞退します。

    今回のテーマは、取得したデータをそのままGridViewにバインドさせるのではなく、一部のカラムを編集するテクニック云々の話ではありません。そのことだけなら、別な方法で解決をしますし、その方法は理解しています。

    単純に、dataSet内に生成された(ストアードプロシージャをドラッグして)厳密に型指定されたデータ テーブルをそっくり、オブジェクトとして、受け渡すクラスを作りたい、という事です。その際、データアダプタのFillメソッドで、全件取り込んだデータを一発でプロパティにセットする方法を見つけたい、という事です。そういう方法ができないのなら、一行ずつ読み込んで、Datasetに一行ずつ追加する方法でやります。この方法なら、出来ないこともないので。

    ただ、このやり方は、接続型でループしてDetasetのテーブルに追加するやり方なので、直観的に避けたい、と思っただけです。

    でも、その方法しかないなら、止むを得ません。(当然、一行ずつやるしかないので)

    以上です。



    • 編集済み 梵天丸 2014年9月21日 13:07
    2014年9月21日 13:06
  • > 私専用のサイトだなんて、思ってもいません。
    > そんな考えは、一切ありません。

    であれば、最初の質問を書き換えるなんてことはしないと思いますけど。


    > 質問を投稿する事がいけないことならこの質問は辞退します。

    そんなことは誰も言ってないでしょう。何故そうすぐ逆ギレするのですか?


    > 本件は、これから先、汎用的に使える技術を知りたくて、ご存知の方が、
    > いらっしゃればご教授いただきたい、そう思っただけです。

    「ご存知の方」は多分多々いると思いますが、あなたが何を知りたいかが明確になってないことは自覚されてますか? 何を知りたいかが分からなければ答えようがないですよね。

    Fill メソッドで生成済みの型付 DataSet/DataTable のインスタンスへの参照を渡すのは、そのインスタンスと、渡す相手のインスタンスが存在していれば何の問題なくできるはず。

    Web アプリはステートレスなので、そうは行かないケースがあるということは認識してますか?

    2014年9月21日 13:24
  • 逆切れ、とかもしていません。

    自分の質問の仕方が良いのか、悪いのかも、判断できないレベルの人間なので、こちらのサイトの方たちにご迷惑をおかけしているようで、申し訳ないと思っただけです。

    あまりに、低レベルの質問を載せてしました。

    申し訳ありませんでした

    2014年9月21日 13:54
  • 低レベルとか思う必要はないです。何を知りたいのか、もう少し明確にすれば回答も得やすいと思います。それが難しいのかもしれませんが、できる限り続けてください。
    2014年9月21日 14:07
  • まぁ、とりあえず。

    なので、繰り返しになりますが、datasetのTABLE_SCHEDULEの内容を、そっくり、一発で、_tblScheduleにセットしてできれば、問題ないのですが、、、つまり『_tblSchedule=TABLE_SCHEDULE』という事をしたのですが、さっぱりうまく行きません。。

    簡単な方法は無いです。地味に行単位でループしながら、各列の値をセットして下さい。この際にデータを加工しても良いと思いますが、別の方法としては、SQL自体で加工してしまうことも考えられます。あまり例が良くないかもしれませんが、
    select 氏名 + ' 様' from テーブル
    なんてすると、氏名に様が付いた状態でfillされます。

    さて、梵天丸さんの考え方自体は正しいと思いますよ。fillしたデータテーブルがDTO(データトランスファオブジェクト)で、_tblScheduleがUI用バインドオブジェクトです。今回、GridViewは表示だけで更新がないのであれば、DTOの段階で加工されており、それを直接バインドした方が楽です(つまり、UI用バインドオブジェクトは必要ありません)。DTOの段階で加工されているのは、上でものべた通りおそらくSQLで対応できると思いますので(特にストアドプロシージャですし)、まずはそちらを検討されてみてはいかがでしょうか? もっとも、用意されたクラスで動的に編集(というか加工ですよね?)したいというのであれば、ごめんなさい。

    #(追記)
    「簡単な方法は無いです。」と書きましたが、UI用バインドオブジェクトの作成を意識してのことです。単純にコピーするのであれば、DataTable.Copyメソッドがあります。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2014年9月22日 1:21
    モデレータ
  • trapemiya さん>

    > 梵天丸さんの考え方自体は正しいと思いますよ。

    全体的なシナリオという意味では、質問者さんは「考え方」は明確にされていません。

    たぶん「考え方」について trapemiya さんの推測が入って「正しい」と言われてると思いますが、もしそうであれば、その推測を書いていただけませんか?

    2014年9月22日 3:49
  • >もしそうであれば、その推測を書いていただけませんか?

    私の書き方が不親切だったかもしれませんが、これは全体的なシナリオの考え方について述べたわけではなくて、データテーブルを直接バインドすると都合が悪い場合は、データテーブルを直接バインドしないという考え方は正しいということについて述べたものです。それに基づき、DTOとUI用バインドオブジェクトをご紹介しました。

    質問者さんが、

    そもそも、こういう事ができないのか、それとも、何か、基本的な考え方が間違っているのか、ちょっと見当が付きません、、、

    と書かれていたことを受けたものです。間違った考え方ではないのですが、それが最適解とは限らないことも述べ、質問者さんが他の方法も含め、一度見直されることも願って、情報を提供しました。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2014年9月22日 5:26
    モデレータ
  • レスを有難うございました。

    質問者さんが提供されている情報ではっきりしているのは、(1) アップされたコードは間違っている、(2) プロパティさえ定義できればやりたいことが実現できると質問者さんは思っている・・・ぐらいだと思っています。

    ここから先は自分の想像ですが、(2) は思い違いではないか? とすると (1) のコードを正しく直してもやりたいことは実現できないのではないか? なので、全体のシナリオ(やりたいこと)が知りたかったのですが・・・


    • 編集済み SurferOnWww 2014年9月22日 6:06 一部追加
    2014年9月22日 5:44
  •  これは、仕事でされていることなのでしょうか。そうであれば、まずは社内(部とか課とかグループとか)に“報告”し、社内で問題の整理をした後、ウェブ コミュニティに提出することを勧めます。
    これには2つの利点があります。
    1.不明瞭な点の行き来を少なくできます。誰がいつ見て、かつ返信してくれるのかどうかわからないウェブ コミュニティに出すより、同じ時間を共有している社内で不明瞭な点を解決する方が、ずっと少ない時間ですみます。
    2.社外に出す前に、情報漏洩を防ぐためのレビューができます。ウェブの向こうの人が「何を聞きたいのかわからない」というから全部書いてしまうと、機密を漏洩してしまうかもしれません。「これくらい自分で判断できる」と思うのは、間違いです。なにを機密とするかは、会社が決めるものです。「こんな情報くらい」と安心しない方が良いです。


    そこで、自前のクラスを作って、そのクラスの中で表示内容を編集して、その結果を受け取り、GridViewにバインドさせる、という構造にしたいと思っています。
    ここからが、本題になると思いますが、クラスの中では、問題なくデータは取得できていて、Datasetに格納されている事も確認できています。なので、問題は、そのDatasetをそっくり、プロパティとしてセットしてあげる事ができれば良い、そう考えました。

     ここで、1行目の「自前のクラスを作って、そのクラスの中で」と、2行目の「クラスの中では」は、同じクラスなのでしょうか。また、2行目の「Dataset」は、自前のクラスの中にあるのでしょうか。それとも、自前のクラスに渡すために、自前のクラスの外にあるのでしょうか。
    …どうも、クラスの外にあるようですけど。もし、『自前のクラス MyDataClass を作って、MyDataClass で表示内容を編集して・・・。ここからが、本題になると思いますが、データ取得を行う MyForm の中では、問題なくデータは取得できていて・・・』と書かれていれば、誤解はないと思いませんか?「クラス」は誰にでも通じますが、文の中の「クラス」が“具体的に”どのクラスを指しているのかは、質問者にしかわからない部分です。「具体的に、これは何?」というところを考えて文を組み立てれば、他の人にも通じやすくなります。

     で、本題ですが、じゃぁ、「自前のクラス」(MyDataClass)で SQL を発行すれば良いんじゃない?と、思いました。
     つまり、「自前のクラスに DataSet を渡したい。でも、上手く渡せない。」という問題のように読めます。だったら、「自前のクラスに渡す」のではなく、自前のクラスに「データ取得を依頼する」「取得したデータを、そのままもらう」「取得したデータを、加工したものをもらう」様にすれば、今問題になっている「自前のクラスに渡す」部分は不要になりますよね?(そして、オブジェクトに志向する(oriented)なら、加工するデータをプロパティ(属性)で渡す、ということはしません。オブジェクトは動作の主体です。オブジェクトを指向する(directed)なら、どうでも良いですけど。)


    つまり、イメージ的には、、、『プロパティ=Dataset』みたいな事をしたい、という事です。

     ここで、「DataSet」と書かれていますが、コーディング内容は、「rsGetScheduleFulDataTable」という名前から、DataTable から派生しているように思います。DataSet と DataTable は異なるクラスなので、渡せません。


    なので、繰り返しになりますが、datasetのTABLE_SCHEDULEの内容を、そっくり、一発で、_tblScheduleにセットしてできれば、問題ないのですが、、、つまり『_tblSchedule=TABLE_SCHEDULE』という事をしたのですが、さっぱりうまく行きません。。

     プロパティは、コードがあって具体的なのに、ここは具体的じゃないですね。「TblSchedule = ds.Tables(0)」とか「TblSchedule = ds.Tables("TABLE_SCHEDULE")」とかでも無理ですか?(メインは C なので、VB コードは自信なし)

     もし、ここ、「DataSet に取り込んだテーブルの中で、テーブル名を指定して取り出すテーブルを決めることができないので、プロパティにテーブルを設定できない」ということが問題であるのなら、文章が多すぎです。聞きたいポイントは何かということも、オフラインで問題を整理する方が速いですよ。
     私たちは、文章を上から読みます。そして、疲れてくると、飛ばします。ですから、重要なことは、先に書きましょう。私が理解した範囲で同じことを質問する場合、次のように書きます。ご自身が投稿されたものと読み比べてみてください。(最初の投稿内容は知りませんが)

    ==============================

    環境:VB2010、VB.NET、Web アプリケーション

    質問:自作クラスのプロパティに、DataSet を渡す方法について。

     SQL Server にあるデータを、GridView に表示します。ここで、表示するデータを、一部編集してから表示したいと考えています。

     これを実現するために、DataSet.Fill メソッドで取得した後、編集用のクラス ChangeForDisplay に用意したプロパティ TblSchedule に渡したいと思います。そのために、次のようにしました。
     まず、プロパティです。

    Class ChangeForDisplay
        Property TblSchedule As dsNaPo.rsGetScheduleFulDataTable
            Get
            Set
        End Property
        (内容は省略)
    End Class
    // C# だと、元の投稿の内容なら、このように Get/Set だけ書けば良いんだけど、VB はダメなの?
    

     次に、データを取得し、表示用に編集する部分です。

    Private Sub とあるメソッド()
        (略)
        Dim ds As New DataSet()
        dtAdapter.Fill(ds, "TABLE_SCHEDULE")
        Dim cfd As New ChageForDisplay()
        cfd.TblSchedule = ????
    End Sub
    

     ここで、cfd.TblSchedule に、テーブル "TABLE_SCHEDULE" を渡す方法がわかりません。「cfd.TblSchedule = ds」としましたが、型が違うとコンパイルが通りません。ds の中のテーブル "TABLE_SCHEDULE" を指定して渡すには、どのようにすれば良いのでしょうか。

    ==============================


    Jitta@わんくま同盟

    2014年9月22日 13:50
  •  あー、TblSchedule As dsNaPo.rsGetScheduleFulDataTable と打ち込んでいるのに、気づかなかった。

     最初の時点で回答が出ていますね。プロパティを厳密に型指定しているので、TblSchedule には dsNaPo.rsGetScheduleFulDataTable 型しか受け入れません。よって、SqlDataAdapter.Fill(DataTable) を使って、プロパティを直接指定すれば良い。

    Dim cfd As New ChageForDisplay()
    dtAdapter.Fill(cfd.TblSchedule)

     タイトルは、適切につけないとね。投稿できないところで見ていて、回答に気がついたから回答候補は設定したけど、その後補足として投稿しようとして探したけど、見つけられなかった。自分の投稿履歴から探せば良いって、やっと気がついた。 


    Jitta@わんくま同盟

    2014年10月6日 23:57
  • jitta さんからレスがあったので一言・・・

    アクセス修飾子の宣言されてないプロパティのアクセスレベルは何になるのでしょう? VB.NET は分かりませんが public にななりますか?

    ThankfulHeart さんの指摘、

    > DataTable の代わりに"dsNaPo.rsGetScheduleFulDataTable"を使用する必要があります。

    は正しいですが、dsNaPo.rsGetScheduleFulDataTable は普通の DataTable を継承しているはずなので、絶対にそうでなければいけないということでもないと思います。(普通の DataTable を受け渡すパブリックプロパティを作ってもいいはず・・・という意味です)

    さらに、Visual Studio のデータソース構成ウィザードを使って型付 DataSet + DataTable を作ったと思いますが、その場合、型付 DataSet のクラスの中に dsNaPo.rsGetScheduleFulDataTable を渡すパブリックプロパティ(ゲッターのみ)が定義済みなので、わざわざ自分でコードを書いてプロパティを定義しなくてもそれが使えるはずです。

    #でもやはり前に書いたように「コードを正しく直してもやりたいことは実現できないのではないか?」と想像しています。


    • 編集済み SurferOnWww 2014年10月7日 2:06 一部追記
    2014年10月7日 2:03