Frage

In .NET gibt es die null Referenz, die überall verwendet wird, um anzuzeigen, dass ein Objektverweis leer ist, und dann gibt es die DBNull, die von Datenbanktreiber verwendet wird (und einige andere) zu bezeichnen ... ziemlich viel das gleiche. Natürlich schafft dies eine Menge Verwirrung und Konvertierungsroutinen werden müssen aufgewühlt, etc.

Also, warum die ursprünglichen .NET Autoren entscheiden, dies zu machen? Für mich macht es keinen Sinn. Ihre Dokumentation macht keinen Sinn, entweder:

Die DBNull-Klasse stellt einen nicht vorhandenen Wert. In einer Datenbank, beispielsweise eine Spalte in einer Zeile einer Tabelle möglicherweise nicht enthält auch immer alle Daten. Das heißt, wird die Säule betrachtet gar nicht existieren, anstatt nur einen Wert hat. Ein DBNull Objekt stellt die nicht vorhandene Spalte. Zusätzlich COM-Interop verwendet die DBNull-Klasse zwischen einer VT_NULL Variante zu unterscheiden, die einen nicht vorhandenen Wertes zeigt, und eine VT_EMPTY Variante, die einen unbestimmten Wert anzeigt.

Was ist das Mist über eine „Spalte nicht vorhanden“? Eine Säule vorhanden ist, es funktioniert einfach nicht einen Wert für die bestimmte Zeile hat. Wenn es nicht gäbe, würde ich eine Ausnahme erhalten versuchen, die spezifische Zelle zugreifen, keinen DBNull! Ich kann verstehen die Notwendigkeit, zwischen VT_NULL und VT_EMPTY, zu unterscheiden, aber warum dann nicht eine COMEmpty Klasse statt machen? Das wäre ein viel ordentlicher Sitz in dem gesamten .NET-Framework sein.

Bin ich etwas fehlt? Kann jemand etwas Licht warum DBNull erfunden wurde und welche Probleme es hilft zu lösen?

War es hilfreich?

Lösung

Der Punkt ist, dass in bestimmten Situationen gibt es einen Unterschied zwischen einer Datenbank Wert ist null und ein .NET Null.

Zum Beispiel. Wenn Sie mit ExecuteScalar (welche die erste Spalte der ersten Zeile in der Ergebnismenge zurückgibt) und Sie erhalten eine Null zurück, dass bedeutet, dass die ausgeführten SQL keine Werte zurückkehrte. Wenn Sie DBNull wieder bedeutet es, ein Wert, der durch die SQL zurückgegeben wurde, und es war NULL. Sie müssen in der Lage, den Unterschied zu erkennen.

Andere Tipps

Ich werde hier mit dem Trend zu widersprechen. Ich werde in den Akten gehen:

Ich bin nicht einverstanden, dass DBNull keinen nützlichen Zweck dient; es fügt unnötige Verwirrung, während praktisch keinen Wert bei.

Das Argument wird oft vorgebracht, dass null eine ungültige Referenz ist, und dass DBNull ist ein Null-Objekt-Muster; ist weder wahr . Zum Beispiel:

int? x = null;

Dies ist keine „ungültige Referenz“; es ist ein null Wert. Tatsächlich null Mittel, was auch immer Sie es bedeuten soll, und ehrlich gesagt habe ich absolut kein Problem mit Werten arbeiten, die null sein kann (in der Tat, auch in SQL müssen wir richtig Arbeit mit null - nichts ändert hier). Ebenso machen die „Null-Objekt Muster“ nur dann Sinn, wenn man es tatsächlich als ein Objekt in OOP Bedingungen behandeln, aber wenn wir einen Wert haben, „unser Wert, oder ein DBNull“ sein kann, dann muss es object sein, so können wir ‚t sinnvoll mit ihm etwas zu tun ist.

Es gibt so viele schlechte Dinge mit DBNull:

  • es zwingt Sie zur Arbeit mit object, da nur object DBNull halten kann oder ein anderer Wert
  • gibt es keinen wirklichen Unterschied zwischen „könnte ein Wert oder DBNull sein“ vs „ein Wert oder null sein könnte“
  • Das Argument, es ergibt sich aus 1.1 (pre-nullable-Typen) ist bedeutungslos; wir null sehr gut in 1.1 verwenden könnte
  • die meisten APIs haben "ist es null?" Verfahren, zum Beispiel DBDataReader.IsDBNull oder DataRow.IsNull - von denen keiner wirklich DBNull erfordern im Hinblick auf die API
  • existieren
  • DBNull nicht in Bezug auf Null-Koaleszenz; value ?? defaultValue funktioniert nicht, wenn der Wert DBNull
  • DBNull.Value kann nicht in optionalen Parameter verwendet werden, da es keine Konstante ist
  • die Runtime-Semantik von DBNull sind auf die Semantik von null identisch; insbesondere DBNull DBNull tatsächlich gleich - so es nicht die Arbeit erledigen, das die Darstellung SQL semantischen
  • zwingt sie oft wert Typ Werte geboxt werden, da es über Anwendungen object
  • wenn Sie zu Test für DBNull benötigen, könnten Sie genauso gut für gerade getestet null
  • es große Probleme für Dinge wie Befehlsparameter verursacht, mit einem sehr dummen Verhalten, wenn ein Parameter einen null Wert hat es nicht gesendet wird ... na ja, hier ist eine Idee: Wenn Sie keinen Parameter gesendet werden sollen - nicht hinzufügen, um es in der Parameter-Auflistung
  • jede ORM ich von Werken denken kann sehr gut ohne jeder Notwendigkeit oder die Verwendung von DBNull, außer als zusätzliche Ärgernis, wenn sie dem ADO.NET Code sprechen

Die einzige auch nur entfernt überzeugendes Argument Ich habe immer sah die Existenz zu rechtfertigen von solchen Wert in DataTable ist, beim Passieren in Werte eine neue Zeile zu erstellen; ein null Mittel „um den Standard verwenden“, ein DBNull ist explizit ein null - ehrlich gesagt diese API, um eine spezifische Behandlung für diesen Fall gehabt haben könnte - eine imaginäre DataRow.DefaultValue zum Beispiel wäre viel besser als ein DBNull.Value Einführung, dass Infekte große Teile des Codes für nicht Grund.

Ebenso das ExecuteScalar Szenario ist ... bestenfalls in; wenn Sie eine skalare Methode ausgeführt werden, können Sie erwarten ein Ergebnis. In dem Szenario, in dem es keine Zeilen, null Rückkehr scheint nicht zu schrecklich. Wenn Sie unbedingt zwischen „keine Reihen“ eindeutig zu machen brauchen, und „eine einzige Null zurückgeführt“, gibt es die Leser-API.

Dieser Schiff fuhr vor langer Zeit, und es ist bei weitem viel zu spät, um es zu beheben. Aber! Bitte beachten Sie nicht denken, dass alle sind sich einig, dassdies ist eine „offensichtlich“ Sache. Viele Entwickler tun nicht sieht Wert in diesen seltsamen Falten auf der BCL.

Ich frage mich wirklich, wenn all dies ergibt sich aus zwei Dinge:

  • mit dem Wort Nothing anstatt etwas beteiligt "null" in VB verwenden
  • in der Lage, uns die if(value is DBNull) Syntax, die „sieht genauso aus wie SQL“, anstatt die ach so heikel if(value==null)

Zusammenfassung:

Mit 3 Optionen (null, DBNull oder ein Ist-Wert) ist nur dann sinnvoll, wenn es ein echtes Beispiel ist, wo Sie müssen zwischen 3 verschiedenen Fällen eindeutig zu machen. Ich habe noch eine Gelegenheit zu sehen, wo ich zwei verschiedene „null“ Zustände darstellen müssen, so DBNull vollständig gegeben ist überflüssig, dass null existiert bereits und hat viel bessere Sprache und Runtime-Unterstützung.

DbNull stellt eine Box ohne Inhalt; null gibt die Nicht-Existenz der Box.

Sie verwenden DBNull für fehlende Daten. Null in der .NET-Sprache bedeutet, dass es kein Zeiger für ein Objekt / Variable.

DBNull Daten fehlen: http://msdn.microsoft. com / en-us / library / system.dbnull.value.aspx

Die Auswirkungen der Daten zur Statistik fehlt:

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

Es gibt einige Unterschiede zwischen einer CLR null und einem DBNull. Erstens, null in relationalen Datenbanken unterschiedliche hat „gleich“ Semantik: null nicht gleich null. CLR null auf NULL gleich.

Aber ich vermute, der Hauptgrund ist mit der Art und Weise Parametern Standardwerte Arbeit in SQL-Server und die Implementierung des Providers zu tun.

Um den Unterschied zu sehen, erstellen Sie eine Prozedur mit einem Parameter, der einen Standardwert hat:

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

Gut strukturierte DAL-Code sollte Befehl Schöpfung aus der Benutzung trennen (ermöglichen, die gleichen Befehl oft verwendet wird, beispielsweise eine gespeicherte Prozedur oft effizient aufzurufen). Schreiben Sie eine Methode, dass die Rendite ein SqlCommand das oben beschriebene Verfahren darstellt:

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

Wenn Sie jetzt rufen Sie den Befehl ohne den @s Parametereinstellung, oder setzen Sie den Wert auf (CLR) null ist, wird es den Standardwert verwenden ‚Hallo‘. Wenn auf der anderen Seite Sie den Parameterwert auf DBNull.Value gesetzt ist, wird es verwenden, dass und Echo DBNull.Value.

Da gibt es zwei unterschiedliche Ergebnisse CLR null oder Datenbank null als Parameterwert verwenden, können Sie nicht beide Fälle repräsentieren mit nur einer von ihnen. Wenn CLR null der einzige zu sein, war, würde es hat die Art und Weise DBNull.Value tut heute arbeiten. Eine Möglichkeit, um anzuzeigen, an den Provider „Ich mag den Standardwert verwenden“ könnte dann sein, um die Parameter nicht überhaupt zu erklären (einen Parameter mit einem Standardwert natürlich Sinn macht, als „optionale Parameter“ zu beschreiben), aber in einem Szenario, in dem der Befehl Objekt zwischengespeichert wird und wieder verwendet führt dies zu entfernen und erneut Hinzufügen des Parameters.

Ich bin mir nicht sicher, ob ich glaube, DBNull eine gute Idee war oder nicht, aber eine Menge Leute sind sich nicht bewusst von den Dingen, die ich hier erwähnt habe, so dass ich es erwähnenswert, dachte.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top