DBNull のポイントは何ですか?
質問
.NET には、 null
これは、オブジェクト参照が空であることを示すためにどこでも使用されます。 DBNull
, 、データベース ドライバー (およびその他のドライバー) によって次のことを示すために使用されます。ほぼ同じこと。当然のことながら、これにより多くの混乱が生じ、変換ルーチンを大量に作成する必要があります。
では、元の .NET 作成者はなぜこれを作成しようとしたのでしょうか?私にとってそれは意味がありません。彼らのドキュメントも意味がありません。
DBNull クラスは存在しない値を表します。たとえば、データベースでは、テーブルの行の列にデータがまったく含まれていない可能性があります。つまり、列には単に値がないのではなく、まったく存在しないと見なされます。DBNull オブジェクトは、存在しない列を表します。さらに、COM 相互運用では、DBNull クラスを使用して、存在しない値を示す VT_NULL バリアントと、未指定の値を示す VT_EMPTY バリアントを区別します。
「列が存在しない」というくだらないことは何ですか?列は存在しますが、特定の行の値がありません。それが存在しない場合、特定のセルにアクセスしようとすると例外が発生します。 DBNull
!区別する必要があることは理解できます VT_NULL
そして VT_EMPTY
, 、しかし、それならなぜ作らないのですか? COMEmpty
代わりにクラス?そうすれば、.NET Framework 全体にもっとうまく適合するでしょう。
何かが足りないのでしょうか?誰かがその理由を明らかにできますか DBNull
が発明されましたが、それはどのような問題の解決に役立ちますか?
解決
ポイントは、特定の状況では、データベース値がnullと.net nullであることに違いがあるということです。
例えば。 executesCalar(結果セットの最初の行の最初の列を返す)を使用している場合、実行されたSQLが値を返さないことを意味するnullバックを取得します。 dbnullを取り戻すと、SQLによって値が返され、nullでした。違いを伝えることができる必要があります。
他のヒント
ここでこの傾向に反対するつもりです。私は記録に行きます:
私はそれに同意しません
DBNull
有用な目的を果たします。それは不必要な混乱を加え、事実上価値がありません。
議論はしばしばそれを提唱します null
無効な参照です DBNull
nullオブジェクトパターンです。 どちらも真実ではありません. 。例えば:
int? x = null;
これは「無効な参照」ではありません。それは null
価値。それはそう null
あなたがそれを意味したいことは何でも意味し、率直に言って、私はまったく価値のある価値で作業するのに問題はありません null
(確かに、SQLであっても、正しく作業する必要があります null
- ここでは何も変わりません)。同様に、「nullオブジェクトパターン」は、実際にそれをOOP用語でオブジェクトとして扱っている場合にのみ理にかなっていますが、「私たちの価値」、または DBNull
「それではそうでなければなりません object
, 、だから私たちはそれで役立つことをすることはできません。
たくさんの悪いことがあります DBNull
:
- それはあなたに働くことを強制します
object
, 、からのみobject
保持することができますDBNull
また 別の値 - 「値になる可能性があるか、
DBNull
「vs」は値になる可能性がありますnull
" - それが1.1(前型型)に起因するという議論は無意味です。使用できます
null
1.1で完全によく - ほとんどのAPIには「nullですか?」たとえば、方法
DBDataReader.IsDBNull
またDataRow.IsNull
- どちらも実際には必要ありませんDBNull
APIの観点から存在する DBNull
ヌルコーテルの観点から失敗します。value ?? defaultValue
値がない場合は機能しませんDBNull
DBNull.Value
一定ではないため、オプションのパラメーターで使用することはできません- のランタイムセマンティクス
DBNull
のセマンティクスと同一ですnull
;特に、DBNull
実際には等しくなりますDBNull
- それはそう ではない SQLセマンティックを表現する仕事をします - 多くの場合、価値のある値を過剰に使用するため、箱入りを強制します
object
- テストする必要がある場合
DBNull
, 、あなたもテストしたかもしれませんnull
- コマンドパラメーターのようなものに大きな問題を引き起こし、パラメーターには
null
それが送信されていない値...まあ、ここにアイデアがあります:パラメーターを送信したくない場合 - パラメータコレクションに追加しないでください - 私が考えることができるすべてのormは完全にうまく機能しません どれか の必要性または使用
DBNull
, 、ADO.NETコードと話すときの余分な迷惑を除いて
唯一の リモートでも 説得力のある議論私は これまで 正当化するために見られます 存在 そのような値があります DataTable
, 、値を渡して新しい行を作成するとき。 a null
「デフォルトの使用」を意味します DBNull
明示的にヌルです - 率直に言って、このAPIはこのケースに特定の治療を受けたかもしれません - 想像上の DataRow.DefaultValue
たとえば、aを導入するよりもはるかに優れています DBNull.Value
それは理由もなく膨大なコードの帯に感染します。
同様に、 ExecuteScalar
シナリオは...せいぜい希薄です。スカラーメソッドを実行している場合は、 予想 結果。行がないシナリオでは、戻ります null
ひどすぎないようです。 「列なし」と「1つの単一のnull返された」の間で絶対に明確にする必要がある場合、読者APIがあります。
この船はずっと前に航海しており、修正するには遅すぎます。だが!してください いいえ 誰もがこれが「明白な」ものであることに同意していると思います。多くの開発者がそうしています いいえ BCLのこの奇妙なしわに値を参照してください。
私は実際に、このすべてが2つのことから生じているのだろうかと思います。
- 単語を使用する必要があります
Nothing
VBの「ヌル」を含む何かの代わりに - 私たちにできること
if(value is DBNull)
「SQLのように見える」、それほど巧妙ではなく構文if(value==null)
概要:
3つのオプションがあります(null
, DBNull
, 、または実際の値)は、3つの異なるケースの間で明確にする必要がある本物の例がある場合にのみ役立ちます。私はまだ2つの異なる「ヌル」状態を表す必要がある機会を見ていないので、 DBNull
それを考えると、完全に冗長です null
すでに存在し、はるかに優れた言語とランタイムのサポートを持っています。
DbNull
内容のないボックスを表します。 null
ボックスの存在を示します。
欠落データにはdbnullを使用します。 .NET言語のnullは、オブジェクト/変数のポインターがないことを意味します。
dbnull欠損データ: http://msdn.microsoft.com/en-us/library/system.dbnull.value.aspx
統計に対するデータの欠落の影響:
CLR null と DBNull の間にはいくつかの違いがあります。まず、リレーショナル データベースの null には、次のような異なる「等しい」セマンティクスがあります。null は null と等しくありません。CLR null は 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 がエコーされます。
CLR null またはデータベース null をパラメーター値として使用すると 2 つの異なる結果が存在するため、どちらか 1 つだけで両方のケースを表すことはできません。CLR null が唯一の場合は、現在の DBNull.Value と同じように動作する必要があります。プロバイダーに「デフォルト値を使用したい」ことを示す 1 つの方法は、パラメータをまったく宣言しないことです (デフォルト値を持つパラメータは、「オプションのパラメータ」として記述するのが当然です)。コマンド オブジェクトがキャッシュされて再利用されるシナリオでは、パラメーターの削除と再追加が必要になります。
DBNull が良いアイデアだと思うかどうかはわかりませんが、多くの人は私がここで述べたことを知らないので、言及する価値があると考えました。