none
DBへのデータの追加 RRS feed

  • 質問

  • こんばんは。

    フォーム上に個人データ(氏名、フリガナ、住所など)があり、これらをDBへ追加する処理を考えています。

    DBへのアクセスするクラスを作り、その中のメソッドのひとつとして組み込むことを考えているのですが、
    その際の引数で困っています。

    いままではAccessを使用していたので、直接フォームのオブジェクトの値をフォーム上でエラーチェックを
    して、関数の引数としてセットしておりました。

    今は同様の方法にて、追加処理を行っているのですが、もし項目が増えた場合など、関数に引数の追加や
    データのエラーチェックもすべてのフォーム上で行う必要があるので、なんとかもうすこしすっきりとした
    形で行うことができないか考えております。

    どうしても、Accessのときのやり方が抜けないのですが、一般的に追加・更新などはどのようにおこなうので
    しょうか。

    また、別の質問にすべきなのですが、関連する内容なので、ここで行わせていただきたいのですが、
    ストアドプロシージャを使って追加・更新を行う場合、各パラメータにDefault値を持たせることにより
    引数を与えなくても処理が可能だと思うのですが、その際は、ストアドプロシージャ内で条件分岐を
    行い、必要なSQL文を組み立てるのでしょうか。
    (Accessの場合は、SQL文の組み立てをフォームのVBAにて行っていました。)

    どうか、アドバイスお願いいたします。
    2009年2月22日 11:09

回答

  • TI-cb400さん の発言:

    どうしても、Accessのときのやり方が抜けないのですが、一般的に追加・更新などはどのようにおこなうので
    しょうか。

    どの方法が一般的というのは難しいところですが、今、TI-cb400さんがされている方法で良いと思います。もうちょっと楽をしようと思えば、データソースにQueryを追加して、それを利用するようにすれば良いと思います。このようにしておけば、追加する項目が変わった際にも、もう一度追加を実行するメソッドを生成し直して、それを使えば済みます。 もちろん、そのメソッドの引数は変わっていますが・・・。
    パラメータに代入するエラーチェックは、フォームで行うのが一般的です。そのパラメータを受け取ってSQL文を実行するメソッドは、正しいパラメータ値が来ると思っていれば大丈夫です。来なければルール違反なので、例外を投げるようにすれば良いでしょう。

    TI-cb400さん の発言:

    ストアドプロシージャを使って追加・更新を行う場合、各パラメータにDefault値を持たせることにより
    引数を与えなくても処理が可能だと思うのですが、その際は、ストアドプロシージャ内で条件分岐を
    行い、必要なSQL文を組み立てるのでしょうか。
    (Accessの場合は、SQL文の組み立てをフォームのVBAにて行っていました。)

    Default値を持たせれば引数を与えなくても大丈夫なのはその通りですが、それがSQL文の組み立てとどうつながるのかわかりませんでした。すみません。ご質問の意図がよくわかりませんでした。ただ、パラメータの値によって、ストアドプロシージャ内で組み立てるSQL文を変えることはよく行います。この時にもSQLインジェクションにならないように、パラメータを使用したSQL文を組み立てて、それを実行します。
    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク TI-cb400 2009年2月23日 12:37
    2009年2月22日 14:50
    モデレータ
  • TI-cb400さん の発言:

    そこで、今回の質問にいたったわけですが、個人的な感想としては、追加・削除については
    クラス化するメリットが少ないように感じるのですが、(基本的に特定のフォームのみで
    該当する内容の追加・更新を行うようにしようと考えているため)
    積極的にクラス化するメリットはあるのでしょうか。


    クラス化することのメリットはあります。それぞれの役割分担がわかりやすく、保守や開発がしやすくなります。しかし、クラス化することにより開発の工数がかかります。つまり、保守や開発のしやすさの実現ということを要求仕様に入れると、それが工数に跳ね返ってきます。小さなアプリケーションであれば保守や開発は比較的楽なので、クラス化するために工数を使っても、あとあとの保守や開発が比較的楽であれば、クラス化するための工数があまり意味のないものになる可能性があります。したがって、その辺りのバランスを考えてクラス化を考えることになると思います。


    TI-cb400さん の発言:

    どうしても、クラスと関数の違いを明確にイメージできておらず、繰り返しのような質問に
    なって申し訳ありません。

    関数やサブルーチンというのは、単にコードの重複を避けているだけのものです。つまり、関数やサブルーチンを呼んでいるところを、そのまま関数やサブルーチンのコードに置き換えることができます。
    しかし、クラスには状態があるため、上記のように単純に置き換えることができません。ここで状態というのは、それぞれのインスタンスが独立した値を保持していることを指しています。荒っぽく言えば、関数と状態をひとまとめにしたものがクラスです。状態はそのクラスを利用する側それぞれに用意しなければなりません。それでインスタンスがたくさん作れるようになっているのです。オブジェクト指向において、インスタンスをたくさん作れるというのはとても重要なことです。もし、インスタンスを一つしか作ることができなければ、あるインスタンスが既に使用されていれば、そのインスタンスの使用が解放されるまで待たなければなりません。というか一つしか作れなければインスタンスという概念自体が必要ありません。クラスだけで十分です。
    状態と関数、つまり属性と動作というのは、世の中を構成している物の基本です。人間だって、車だって飛行機だって、属性と動作を持っています。したがって属性と動作、つまりフィールドとメソッドを持ったクラスを物(オブジェクト)として考え、この物同士が作用し合って動作するプログラミング方法をオブジェクト指向というのです。

    TI-cb400さん の発言:

    そこで、
    UPDATE テーブル名 SET
    IF a=1 THEN 
       F1=P1
    Elseif b=2 THEN
        F2 =P2

    といった形で、必要な項目のみを拾ってSQL文が作れないかと思ったのです。



    可能です。パラメータを使用してSQL文を組み立て、sp_executesqlで実行して下さい。

     
    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク TI-cb400 2009年2月24日 3:12
    2009年2月23日 15:13
    モデレータ
  • TI-cb400さん の発言:

    (もし、上に書いてあるプロパティの使い方が間違っているようであれば、どうかご指摘ください。)

    最初にエラーチェックと例外の違いを認識して下さい。エラーチェックというのは間違った値が来ることが想定されている場合に行います。例えば日付の範囲を指定する場合、開始日付と終了日付を逆に入力されるのは想定できることです。一方、例外というのは来るはずのない値が間違ってきてしまった場合、つまりアプリケーションが正常な動作をしていないため、アプリケーションの動作を停止した方が良い場合に発動します。だからcatchしなければアプリケーションは終了します。
    つまり、エラーチェックの場合はあくまでもアプリケーションは正常動作していますし、例外の場合は正常動作していないことになります。これが原則です。といいますのも、SQL Serverなどのデータベースで例外が発生した場合、それはアプリケーションとしては正しく動作している場合があるからです。その場合は例外であってもエラーチェックと同様に考えます。つまり、例外をエラーチェックに置き換えてアプリケーションを続行します。
    (Javaには検査例外とか業務例外とかいうのがあって、例外と言ってもこのようにエラーチェックに近い例外があるそうです。)
    参考
    .NETとJavaの例外処理の違い
    http://blogs.msdn.com/nakama/archive/2009/01/09/net-java.aspx

    さて、プロパティでのエラーチェックに戻ります。プロパティでエラーチェックし、エラーがあった場合は例外を発生させてセット元に通知することが多いでしょう。なぜなら、プロパティを持っているクラスと、そのプロパティにセットするクラスとは異なるため、クラス間でエラーチェックの結果を通知しなければならず、確実に通知できるのは例外を発生させることだからです。
    先に述べた通り、.NETの世界では基本的に例外は緊急事態です。したがってプロパティでエラーチェックして例外を返すことはあまり好ましいことではないと思います。なので、プロパティを渡すクラスでエラーチェックし、プロパティがあるクラスでは正しい値が来ることを前提で待っていれば良いでしょう。それでもコーディングミスでエラーチェックをくぐりぬけてくる場合があるでしょうから、その際はプロパティがあるクラスで例外を発生するようにしておけば完璧だと思います。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク TI-cb400 2009年2月24日 8:41
    2009年2月24日 5:28
    モデレータ

すべての返信

  • TI-cb400さん の発言:

    どうしても、Accessのときのやり方が抜けないのですが、一般的に追加・更新などはどのようにおこなうので
    しょうか。

    どの方法が一般的というのは難しいところですが、今、TI-cb400さんがされている方法で良いと思います。もうちょっと楽をしようと思えば、データソースにQueryを追加して、それを利用するようにすれば良いと思います。このようにしておけば、追加する項目が変わった際にも、もう一度追加を実行するメソッドを生成し直して、それを使えば済みます。 もちろん、そのメソッドの引数は変わっていますが・・・。
    パラメータに代入するエラーチェックは、フォームで行うのが一般的です。そのパラメータを受け取ってSQL文を実行するメソッドは、正しいパラメータ値が来ると思っていれば大丈夫です。来なければルール違反なので、例外を投げるようにすれば良いでしょう。

    TI-cb400さん の発言:

    ストアドプロシージャを使って追加・更新を行う場合、各パラメータにDefault値を持たせることにより
    引数を与えなくても処理が可能だと思うのですが、その際は、ストアドプロシージャ内で条件分岐を
    行い、必要なSQL文を組み立てるのでしょうか。
    (Accessの場合は、SQL文の組み立てをフォームのVBAにて行っていました。)

    Default値を持たせれば引数を与えなくても大丈夫なのはその通りですが、それがSQL文の組み立てとどうつながるのかわかりませんでした。すみません。ご質問の意図がよくわかりませんでした。ただ、パラメータの値によって、ストアドプロシージャ内で組み立てるSQL文を変えることはよく行います。この時にもSQLインジェクションにならないように、パラメータを使用したSQL文を組み立てて、それを実行します。
    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク TI-cb400 2009年2月23日 12:37
    2009年2月22日 14:50
    モデレータ
  • ご回答ありがとうございます。

    ヘルプやいろいろなサイトを参考にしながら、とりあえず追加・更新ができるというところまで
    できるようにはなったのですが、統一的な記述ができればと再検討をしているところです。

    そこで、今回の質問にいたったわけですが、個人的な感想としては、追加・削除については
    クラス化するメリットが少ないように感じるのですが、(基本的に特定のフォームのみで
    該当する内容の追加・更新を行うようにしようと考えているため)
    積極的にクラス化するメリットはあるのでしょうか。

    データの検索などについては、汎用的にできたほうが良いことは理解ができるのですが。

    どうしても、クラスと関数の違いを明確にイメージできておらず、繰り返しのような質問に
    なって申し訳ありません。
    (今後、JAVAやC#も勉強したいと思っているのですが、こちらは基本的にすべてをクラスで
    記述するということを目にしたので、これらで追加・更新などはどのように行っているかも
    気になります。)
    ちょっと横道にそれて申し訳ありません。

    SQL文を組み立てる件ですが、更新クエリで必要な項目のみ更新をするとします。
    フィールドが3個有、(F1 F2 F3とします。)、パラメータも3個(P1 P2 P3)
    とします。

    そこで、
    UPDATE テーブル名 SET
    IF a=1 THEN 
       F1=P1
    Elseif b=2 THEN
        F2 =P2

    といった形で、必要な項目のみを拾ってSQL文が作れないかと思ったのです。


    2009年2月23日 12:54
  • TI-cb400さん の発言:

    そこで、今回の質問にいたったわけですが、個人的な感想としては、追加・削除については
    クラス化するメリットが少ないように感じるのですが、(基本的に特定のフォームのみで
    該当する内容の追加・更新を行うようにしようと考えているため)
    積極的にクラス化するメリットはあるのでしょうか。


    クラス化することのメリットはあります。それぞれの役割分担がわかりやすく、保守や開発がしやすくなります。しかし、クラス化することにより開発の工数がかかります。つまり、保守や開発のしやすさの実現ということを要求仕様に入れると、それが工数に跳ね返ってきます。小さなアプリケーションであれば保守や開発は比較的楽なので、クラス化するために工数を使っても、あとあとの保守や開発が比較的楽であれば、クラス化するための工数があまり意味のないものになる可能性があります。したがって、その辺りのバランスを考えてクラス化を考えることになると思います。


    TI-cb400さん の発言:

    どうしても、クラスと関数の違いを明確にイメージできておらず、繰り返しのような質問に
    なって申し訳ありません。

    関数やサブルーチンというのは、単にコードの重複を避けているだけのものです。つまり、関数やサブルーチンを呼んでいるところを、そのまま関数やサブルーチンのコードに置き換えることができます。
    しかし、クラスには状態があるため、上記のように単純に置き換えることができません。ここで状態というのは、それぞれのインスタンスが独立した値を保持していることを指しています。荒っぽく言えば、関数と状態をひとまとめにしたものがクラスです。状態はそのクラスを利用する側それぞれに用意しなければなりません。それでインスタンスがたくさん作れるようになっているのです。オブジェクト指向において、インスタンスをたくさん作れるというのはとても重要なことです。もし、インスタンスを一つしか作ることができなければ、あるインスタンスが既に使用されていれば、そのインスタンスの使用が解放されるまで待たなければなりません。というか一つしか作れなければインスタンスという概念自体が必要ありません。クラスだけで十分です。
    状態と関数、つまり属性と動作というのは、世の中を構成している物の基本です。人間だって、車だって飛行機だって、属性と動作を持っています。したがって属性と動作、つまりフィールドとメソッドを持ったクラスを物(オブジェクト)として考え、この物同士が作用し合って動作するプログラミング方法をオブジェクト指向というのです。

    TI-cb400さん の発言:

    そこで、
    UPDATE テーブル名 SET
    IF a=1 THEN 
       F1=P1
    Elseif b=2 THEN
        F2 =P2

    といった形で、必要な項目のみを拾ってSQL文が作れないかと思ったのです。



    可能です。パラメータを使用してSQL文を組み立て、sp_executesqlで実行して下さい。

     
    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク TI-cb400 2009年2月24日 3:12
    2009年2月23日 15:13
    モデレータ
  • ご回答ありがとうございます。

    教えていただいたことを元に実際に作っていってみて、感触をつかんでいきたいと思います。

    参考書などを見ていたら、クラスにプロパティを作ることができ、こちらでもエラーチェックなどを
    記述できるという内容があったので、パラメータのエラーチェックはいずれにしても必須なので
    今回はこちらで実装してみたいと思います。

    今回教えていただいたように、私が行いたいと考えていることはクラスにするほうがかえって手間が
    かかりそうですが、自分の勉強をかねており、また、自分自身が行っている作業の簡略化のための
    アプリケーション作りなので、いろいろと試してみたいと思っています。

    また、困ったときはよろしくお願いします。
    (もし、上に書いてあるプロパティの使い方が間違っているようであれば、どうかご指摘ください。)
    2009年2月24日 3:17
  • TI-cb400さん の発言:

    (もし、上に書いてあるプロパティの使い方が間違っているようであれば、どうかご指摘ください。)

    最初にエラーチェックと例外の違いを認識して下さい。エラーチェックというのは間違った値が来ることが想定されている場合に行います。例えば日付の範囲を指定する場合、開始日付と終了日付を逆に入力されるのは想定できることです。一方、例外というのは来るはずのない値が間違ってきてしまった場合、つまりアプリケーションが正常な動作をしていないため、アプリケーションの動作を停止した方が良い場合に発動します。だからcatchしなければアプリケーションは終了します。
    つまり、エラーチェックの場合はあくまでもアプリケーションは正常動作していますし、例外の場合は正常動作していないことになります。これが原則です。といいますのも、SQL Serverなどのデータベースで例外が発生した場合、それはアプリケーションとしては正しく動作している場合があるからです。その場合は例外であってもエラーチェックと同様に考えます。つまり、例外をエラーチェックに置き換えてアプリケーションを続行します。
    (Javaには検査例外とか業務例外とかいうのがあって、例外と言ってもこのようにエラーチェックに近い例外があるそうです。)
    参考
    .NETとJavaの例外処理の違い
    http://blogs.msdn.com/nakama/archive/2009/01/09/net-java.aspx

    さて、プロパティでのエラーチェックに戻ります。プロパティでエラーチェックし、エラーがあった場合は例外を発生させてセット元に通知することが多いでしょう。なぜなら、プロパティを持っているクラスと、そのプロパティにセットするクラスとは異なるため、クラス間でエラーチェックの結果を通知しなければならず、確実に通知できるのは例外を発生させることだからです。
    先に述べた通り、.NETの世界では基本的に例外は緊急事態です。したがってプロパティでエラーチェックして例外を返すことはあまり好ましいことではないと思います。なので、プロパティを渡すクラスでエラーチェックし、プロパティがあるクラスでは正しい値が来ることを前提で待っていれば良いでしょう。それでもコーディングミスでエラーチェックをくぐりぬけてくる場合があるでしょうから、その際はプロパティがあるクラスで例外を発生するようにしておけば完璧だと思います。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク TI-cb400 2009年2月24日 8:41
    2009年2月24日 5:28
    モデレータ
  • ご回答ありがとうございます。

    エラーチェックについて、まさしくおっしゃるとおりに勘違いをしておりました。

    ご呈示の内容で、プロパティを持っているクラスとプロパティにセットするクラスが違うというくだりがあったのですが
    これはどのようなことを刺すのでしょうか。

    現在考えているのは、

    public class TableIO
     ’内部変数

      '各種プロパティのセット

     ’データの追加メソッド
    end class

    ということを考えていたのですが、プロパティのセットは別のクラスにしたほうが良いのでしょうか。

    それとも、まったく見当違いのことを私が考えているのでしょうか。

    どうか、よろしくお願いします。
    2009年2月24日 8:49