none
DataTable によるメモリー上のDBで、null 入力を認めるデータ型を設定する方法は? RRS feed

  • 質問

  • こんばんわ!
    皆様、お世話になります。

    早速ですが、質問に入らせて頂きます。

        DataTable workTable = new DataTable();
        workTable.Columns.Add("日付", typeof(DateTime));

    と言う感じで、テーブルのデザインを行っていますが、上記の「日付」カラムが、
    null 入力も許すようにしたいのですが、色々調べてみても答えに到達しません。
    データ型をどのように設定すれば宜しいのでしょうか、ご教授ください。

    どうぞ、よろしくお願いします。

    2010年10月5日 10:57

回答

  • DataTable では、NULL 値を DBNull.Value で表現します。特に値型の列では代入にも null を使うことはできず、必ず DBNull.Value を使う必要があります。

    NULL チェックも、null ではなく DBNull.Value との比較を行います。

    2010年10月5日 12:39
  • DataColumn の AllowDBNull を true に設定すれば null を許容するようになりますが、そもそも AllowDBNull は true が既定値なので普通はそのままで問題ないはずです。

    ということぐらいはご存知と思いますが、その上で何かお困りでしょうか。

    2010年10月5日 11:02
  • > DBの一部のレコードをローカルに取り込み処理がしたかったため、あちこち探してみた所、
    > 「DataTableによるメモリー上のデータベース」の記事が見つかり、これを真似ている
    > 状況で、全くの初心者・何も分かっていません。

    その DB をベースに Visual Studio のウィザードを使って、型付 DataSet + TableAdapter
    を作成して使ってはいかがですか?

    DataSet/DataTable に DB からデータを取り込むのに、自力でコードを書くのは 3 行ぐらい
    ですむはずです。

    DataSet への手動でのデータの入力などは、自動生成される型付 DataSet + TableAdapter
    のコードの中に、データを取り扱うためのpublic のプロパティ、メソッドが定義されていま
    すので、それを使えば間違いないと思います。

    たとえば、DB の Orders という名前のテーブルに ShippedDate という名前のフィールドが
    ある場合、以下のようなメソッドが自動生成されます。

    public partial class OrdersRow : global::System.Data.DataRow {

        ・・・中略・・・

        public bool IsShippedDateNull() {
            return this.IsNull(this.tableOrders.ShippedDateColumn);
        }
               
        public void SetShippedDateNull() {
           this[this.tableOrders.ShippedDateColumn] = global::System.Convert.DBNull;
        }

    従って、以下のように null を設定するなら、

    > record["日時"] = 「取得先のDBからのデータが null」

    record.Set日時Null() という感じでいけます。

    null か否かを確認するなら record.Is日時Null() といった感じです。

    2010年10月5日 14:40

すべての返信

  • DataColumn の AllowDBNull を true に設定すれば null を許容するようになりますが、そもそも AllowDBNull は true が既定値なので普通はそのままで問題ないはずです。

    ということぐらいはご存知と思いますが、その上で何かお困りでしょうか。

    2010年10月5日 11:02
  • Hongliang さん、早速の返信有難うございます。

    DBの一部のレコードをローカルに取り込み処理がしたかったため、あちこち探してみた所、
    「DataTableによるメモリー上のデータベース」の記事が見つかり、これを真似ている
    状況で、全くの初心者・何も分かっていません。
    (よく分からないままの投稿で、皆さんには大変失礼でご迷惑をお掛けしていますが
     ご容赦ください。)
     
    問題が生じているのは、先の投稿に書いた方法で、メモリー上のDB・テーブルを作り、
    SQL DB上の1レコードをここに追加しようと、

        DataRow record;
        record = workTable.NewRow();

    と、1レコード作成してこの中の各カラムに値をセットしている中で

        record["日時"] = 「取得先のDBからのデータが null」 の際に

    「列'日時'をNullに設定できません。DBNullを使用してください。」と要求されます。

    このカラムは、SQL DB上で NULLを許容にチェックを入れているため、メモリー上の
    テーブルでも同じようなデータ型のカラムに設定を行いたいのです。

    workTable.Columns.Add("日付", typeof(DateTime)); でAdd以降の()内の設定方法を
    調べてみましたが、どうして良いのかよく分かりません。

    どうか、よろしくお願いいたします。

    2010年10月5日 11:51
  • DataTable では、NULL 値を DBNull.Value で表現します。特に値型の列では代入にも null を使うことはできず、必ず DBNull.Value を使う必要があります。

    NULL チェックも、null ではなく DBNull.Value との比較を行います。

    2010年10月5日 12:39
  • Hongliang さん、有難うございます。

    DataTable では、null をそのまま使用できないと言う事なのですね。

    従って、他の「null」を持ったテーブルの写しを作る時には、行きと帰りで
    null と DBNull.Value の変換(?)が必要と理解しました。

    その考えで、手直しを加えたところ思ったように動くようになりましたので、
    上記の理解でOKかな、と思っています。

    まだ、理解が間違っているようでしたら、その旨教えてください。
    今後とも、どうぞよろしくお願いいたします。

    これで、一旦クローズさせて頂きます。
    どうも、有難うございました。

    2010年10月5日 13:20
  • > DBの一部のレコードをローカルに取り込み処理がしたかったため、あちこち探してみた所、
    > 「DataTableによるメモリー上のデータベース」の記事が見つかり、これを真似ている
    > 状況で、全くの初心者・何も分かっていません。

    その DB をベースに Visual Studio のウィザードを使って、型付 DataSet + TableAdapter
    を作成して使ってはいかがですか?

    DataSet/DataTable に DB からデータを取り込むのに、自力でコードを書くのは 3 行ぐらい
    ですむはずです。

    DataSet への手動でのデータの入力などは、自動生成される型付 DataSet + TableAdapter
    のコードの中に、データを取り扱うためのpublic のプロパティ、メソッドが定義されていま
    すので、それを使えば間違いないと思います。

    たとえば、DB の Orders という名前のテーブルに ShippedDate という名前のフィールドが
    ある場合、以下のようなメソッドが自動生成されます。

    public partial class OrdersRow : global::System.Data.DataRow {

        ・・・中略・・・

        public bool IsShippedDateNull() {
            return this.IsNull(this.tableOrders.ShippedDateColumn);
        }
               
        public void SetShippedDateNull() {
           this[this.tableOrders.ShippedDateColumn] = global::System.Convert.DBNull;
        }

    従って、以下のように null を設定するなら、

    > record["日時"] = 「取得先のDBからのデータが null」

    record.Set日時Null() という感じでいけます。

    null か否かを確認するなら record.Is日時Null() といった感じです。

    2010年10月5日 14:40
  • SurferOnWww さん、いつもありがとう御座います。

    折角教えて頂いた何か利口(便利)な方法があるようですが、色々探して
    みましたが、残念ながら今の私の知識ではVisual Studioのウィザードにすら
    到達していません。

    もう少し勉強して、具体的な質問だできるようになったら、改めて質問など
    投稿させて頂きますので、その節にはどうかよろしくお願いします。

    今は折角のお教えが生かせず申し訳ありませんが、もう少しがんばってみます。
    ありがとう御座いました。

    2010年10月12日 0:59