76

.NETにはnull、オブジェクト参照が空であることを示すためにどこでも使用される参照があります。次に、DBNullデータベースドライバー(および他のいくつか)によって使用される参照があります...ほとんど同じことを示します。当然、これは多くの混乱を引き起こし、変換ルーチンを解き放つ必要があります。

では、なぜ元の.NET作成者がこれを作成することにしたのでしょうか。私にはそれは意味がありません。彼らのドキュメントも意味がありません:

DBNullクラスは、存在しない値を表します。たとえば、データベースでは、テーブルの行の列にデータがまったく含まれていない場合があります。つまり、列は単に値を持たないのではなく、まったく存在しないと見なされます。DBNullオブジェクトは、存在しない列を表します。さらに、COM相互運用機能はDBNullクラスを使用して、存在しない値を示すVT_NULLバリアントと、指定されていない値を示すVT_EMPTYバリアントを区別します。

「列が存在しない」についてのこのがらくたは何ですか?列が存在しますが、特定の行の値がありません。存在しなかった場合、DBNull!ではなく、特定のセルにアクセスしようとすると例外が発生します。VT_NULLとを区別する必要があることは理解できますが、代わりにクラスをVT_EMPTY作成してみませんか?COMEmptyこれは、.NETFramework全体に非常にうまく適合します。

私は何かが足りないのですか?なぜDBNull発明されたのか、それがどのような問題を解決するのに役立つのか、誰かが光を当てることができますか?

4

6 に答える 6

184

私はここでの傾向に反対するつもりです。私は記録に残ります:

DBNull私はそれが有用な目的に役立つことに同意しません。それは不必要な混乱を追加しますが、実質的に価値はありません。

null多くの場合、無効な参照でありDBNull、nullオブジェクトパターンである引数が提示されます。どちらも真実ではありません。例えば:

int? x = null;

これは「無効な参照」ではありません。それはnull値です。確かnullに、あなたが意味したいことは何でも意味します。率直に言って、私は値を操作するのにまったく問題はありませんnull(実際、SQLでも正しく操作する必要がありますnull-ここでは何も変更されません)。同様に、「nullオブジェクトパターン」は、実際にOOP用語でオブジェクトとして扱っている場合にのみ意味がありますが、「私たちの値」またはDBNull「」になり得る値がある場合は、そうである必要がobjectあるため、できません。それで何か役に立つことをしている。

悪いことがたくさんありますDBNull

  • 保持できるのは、または別の値objectのみであるため、objectDBNull
  • DBNull「値になる可能性がある」と「値になる可能性があるnull」との間に実際の違いはありません
  • 1.1(pre-nullable-types)に由来するという議論は無意味です。null1.1では完璧に使用できました
  • ほとんどのAPIには「nullですか?」たとえばDBDataReader.IsDBNull、またはDataRow.IsNull-どちらもDBNullAPIの観点から実際に存在する必要はありません。
  • DBNullnull合体に関して失敗します。value ?? defaultValue値がDBNull
  • DBNull.Value定数ではないため、オプションのパラメータでは使用できません
  • の実行時セマンティクスは、 ;DBNullのセマンティクスと同じです。null特に、DBNull実際には等しいDBNull-したがって、SQLセマンティクスを表す役割はありません
  • 過剰に使用するため、値型の値を強制的にボックス化することがよくあります。object
  • をテストする必要がある場合はDBNullnull
  • それはコマンドパラメータのようなものに大きな問題を引き起こし、パラメータにnull値がある場合は送信されないという非常にばかげた振る舞いをします...まあ、ここにアイデアがあります:パラメータを送信したくない場合は-しないでくださいパラメータコレクションに追加します
  • 私が考えることができるすべてのORMは、ADO.NETコードと通信するときの余分な迷惑を除いて、を必要とせずに使用することなく完全に機能します。DBNull

そのような値の存在を正当化するために私が今まで見た中で唯一のリモートで説得力のある議論は、新しい行を作成するために値を渡すときです。aは「デフォルトを使用する」を意味し、aは明示的にnullです-率直に言って、このAPIはこの場合に特定の処理を行うことができます-たとえば、理由もなく膨大な量のコードに感染するを導入するよりも、架空のものの方がはるかに優れています。DataTablenullDBNullDataRow.DefaultValueDBNull.Value

同様に、ExecuteScalarシナリオは...せいぜい希薄です。スカラーメソッドを実行している場合は、結果が期待できます。行がないシナリオでは、戻るnullことはそれほどひどくはないようです。「行なし」と「単一のnullが返される」を明確にする必要がある場合は、リーダーAPIがあります。

この船はずっと前に出航しており、修理するには遅すぎます。だが!これが「明らかな」ことであることに誰もが同意するとは思わないでください。多くの開発者は、BCLのこの奇妙なしわに価値を見ていません。

私は実際、これらすべてが2つのことに起因するのだろうかと思います。

  • NothingVBで「null」を含むものの代わりに単語を使用する必要がある
  • if(value is DBNull)非常にトリッキーではなく、「SQLのように見える」構文を使用できるようになりますif(value==null)

概要:

3つのオプション(、、、nullまたはDBNull実際の値)があると、3つの異なるケース間で曖昧さを解消する必要がある本物の例がある場合にのみ役立ちます。2つの異なる「ヌル」状態を表す必要がある場合はまだ見たことがないので、すでに存在し、言語とランタイムのサポートがはるかに優れているDBNullことを考えると、完全に冗長です。null

于 2012-03-09T09:56:04.827 に答える
48

重要なのは、特定の状況では、データベース値がnullであるのと.NETNullであるのとの間に違いがあるということです。

例えば。ExecuteScalar(結果セットの最初の行の最初の列を返す)を使用していて、実行されたSQLが値を返さなかったことを意味するnullが返される場合。DBNullが返される場合は、SQLによって値が返され、NULLであったことを意味します。あなたは違いを見分けることができる必要があります。

于 2010-12-20T10:28:16.140 に答える
15

DbNull内容のないボックスを表します。nullボックスが存在しないことを示します。

于 2010-12-20T10:35:07.267 に答える
0

欠落データにはDBNullを使用します。.NET言語のnullは、オブジェクト/変数へのポインターがないことを意味します。

DBNullの欠落データ:http://msdn.microsoft.com/en-us/library/system.dbnull.value.aspx

欠測データが統計に与える影響:

http://en.wikipedia.org/wiki/Missing_values

于 2010-12-20T10:33:38.010 に答える
0

CLRnullとDBNullの間にはいくつかの違いがあります。まず、リレーショナルデータベースのnullには、異なる「等しい」セマンティクスがあります。nullはnullと等しくありません。CLRnullはnullと同じです。

しかし、主な理由は、SQLサーバーでのパラメーターのデフォルト値の動作とプロバイダーの実装に関係していると思われます。

違いを確認するには、デフォルト値を持つパラメーターを使用してプロシージャーを作成します。

CREATE PROC [Echo] @s varchar(MAX) = 'hello'
AS
    SELECT @s [Echo]

適切に構造化されたDALコードは、コマンドの作成と使用を分離する必要があります(たとえば、ストアドプロシージャを何度も効率的に呼び出すために、同じコマンドを何度も使用できるようにするため)。上記の手順を表すSqlCommandを返すメソッドを記述します。

SqlCommand GetEchoProc()
{
    var cmd = new SqlCommand("Echo");
    cmd.Parameters.Add("@s", SqlDbType.VarChar);
    return cmd;
}

@sパラメータを設定せずにコマンドを呼び出すか、その値を(CLR)nullに設定すると、デフォルト値の「hello」が使用されます。一方、パラメータ値をDBNull.Valueに設定すると、それが使用され、DbNull.Valueがエコーされます。

パラメータ値としてCLRnullまたはデータベースnullを使用した2つの異なる結果があるため、どちらか一方だけで両方のケースを表すことはできません。CLR nullが唯一のものである場合、DBNull.Valueが今日行うのと同じように機能する必要があります。プロバイダーに「デフォルト値を使用したい」ことを示す1つの方法は、パラメーターをまったく宣言しないことです(もちろん、デフォルト値を持つパラメーターは「オプションのパラメーター」として説明するのが理にかなっています)。コマンドオブジェクトがキャッシュされて再利用されるシナリオでは、これはパラメータの削除と再追加につながります。

DBNullが良いアイデアかどうかはわかりませんが、多くの人がここで述べたことに気付いていないので、言及する価値があると思いました。

于 2013-05-02T16:43:51.267 に答える
0

あなたの質問に答えるには、なぜDBNullが存在するのかを考慮する必要があります。

狭いユースケースではDBNullが必要です。そうでなければ、そうではありません。ほとんどの人はDBNullを必要としません。私が設計したデータストアにそれらを入力することは決して許可しません。私は常に値を持っているので、データが「<null>」になることはありません。常に意味のあるタイプの「デフォルト値」を選択します。コード内ですべてを2回チェックする必要はありません。一度は、オブジェクトnullです。また、オブジェクトを実際のデータ型(Intなど)にキャストする前のDBNullです。

DBNullが必要になる場合があります...SQL統計関数の一部(中央値、平均など)を使用する場合..DBNullを特別に扱います..これらのドキュメントを参照してください..一部の関数にはDBNullが含まれていません統計の合計数で...例:(87合計/ 127合計)vs。(87合計/合計117)..これらの列値の10個がDBNullであるという違い...これが変更されることがわかります統計結果。

DBNullを使用してデータベースを設計する必要はありません。統計結果が必要な場合は、存在しないために何らかの特別な処理が必要な1つのアイテムに対して、「UserDidProvideValue」などの列を明示的に作成または追加します(たとえば、合計117は、マークされたフィールドの合計になります) UserDidProvideValue = true)...hahalol-宇宙の支配者としての私の次の人生ではlol-DBNullがSQL領域から脱出することは決して許されなかったでしょう...プログラミングの世界全体が今やすべてを2回チェックする負担になっています...モバイルアプリ、デスクトップアプリ、またはWebサイトで「null」整数が必要になったことがありますか。- 一度もない...

于 2020-06-27T15:50:45.603 に答える