Warum nicht Daten als Zeichenfolge aus der Datenbank zurückgeben?

41

In einer typischen Webanwendung werden Datumsangaben aus der stark typisierten Datenbankebene abgerufen (z. B. in c # als System.DateTime im Gegensatz zu System.String).

Wenn ein Datum als Zeichenfolge ausgedrückt werden muss (z. B. auf einer Seite angezeigt werden soll), erfolgt die Konvertierung von DateTime in Zeichenfolge in der Präsentationsschicht.

Warum ist das? Warum ist es eine schlechte Sache, die DateTime in eine Zeichenfolge auf der Datenbankebene zu konvertieren?

Siehe auch die hitzige Debatte im Chat und die ursprüngliche Frage, die all dies ausgelöst hat .

John Wu
quelle
73
Ich frage Sie: Würden Sie dann einfach jeden einzelnen Typ in einen String umwandeln? Was macht Date anders?
Gardenhead
7
Gute Frage! Sehen Sie sich hier die hitzige Debatte an .
John Wu
8
Nun, es scheint ziemlich offensichtlich, dass der andere Typ falsch liegt und alle anderen Recht haben. Keine wirkliche Frage hier
gardenhead
7
Manchmal müssen Sie Datumsberechnungen außerhalb der Datenbank durchführen. Beträchlich schwieriger, wenn Sie nur Saiten haben.
Eric King
14
Ein weiteres Problem - welche Art von Zeichenfolge benötigen Sie? Es gibt viele Möglichkeiten, eine Datums- und Uhrzeitangabe als Zeichenfolge darzustellen. Was wäre, wenn ich eine Datenbank hätte, die nur die aktuelle Zeit, dargestellt als Anzahl der Sekunden seit der Epoche, als Zeichenfolge zurückgibt (zum Beispiel lautet die aktuelle Zeit "1474496980"). Wäre das nützlich? Möchten Sie eine solche Datenbank verwenden?
Riwalk

Antworten:

168

Dates, DateTimes und wirklich alle anderen typisierten Objekte sollten im Allgemeinen in ihrem korrekt typisierten Format belassen werden, bis sie in einen anderen Typ umgewandelt werden müssen - insbesondere, wenn dieser Typ für Menschen lesbar ist und insbesondere, wenn es sich um ein verlustbehaftetes Objekt handelt. One-Way-Art der Konvertierung.

Warum? Da davon ausgegangen wird, dass der Typ viele praktische Funktionen bietet, wie z. B. die Prüfung der Gleichheit, Addition und Subtraktion, Vergleich (größer als, kleiner als), Zeitzonen- und Gebietsschemafunktionalität (besonders wichtig für alles, was mit Zeit zu tun hat). usw. Wenn Sie Amerikaner und das Format "Month Day [th], Year" sowie den gängigen britischen Stil "Day Month Year" oder den ISO-Standard "Year-Month-Day" unterstützen möchten? Was würden Sie tun, wenn es sich um eine Zeichenfolge handeln würde und Sie diese Änderung vornehmen müssten, um sie wieder in ein Datum umzuwandeln? Puh, nein danke - es gibt so viele Übel und abscheuliche Bugs, die man am besten komplett vermeiden kann.

Insbesondere haben Sie die gestufte Architektur erwähnt, bei der die Präsentationsschicht später von den Daten getrennt wird. Dies ist eigentlich der andere wichtige Grund, ein Datum als Datum und nicht als Zeichenfolge zu übergeben. In welcher Zeichenfolgenformatierung soll das Datum eingegeben werden? Englisch, Chinesisch, mit oder ohne Sekunden / Millisekunden, vollständiger Monatsname oder Ziffern, möchten Sie später nach dem Datumsfeld sortieren (das Sortieren nach einer Zeichenfolge erfordert ein bestimmtes Zeichenfolgenformat, wenn es richtig funktionieren soll) usw.? Dies alles ist eine Frage der Präsentation - wie der Benutzer die Daten anzeigen sollte - und das Anordnen dieser Logik an einer anderen Stelle würde den Vorteil einer abgestuften Architektur an erster Stelle einschränken. Die Datenbank muss nicht wissen oder kümmern, wie Sie das Datum in Zukunft anzeigen möchten.

Schließlich verwenden fast alle komplexen Anwendungen (für die mehrstufige Architekturen vorgesehen sind), bei denen es um Zeit geht, unweigerlich Zeiten / Daten auf viele verschiedene Arten und oft auf allen verschiedenen Ebenen der Architektur. Die typisierten Objekte, die sich auf Zeiten und Daten beziehen, existieren aus einem wirklich guten Grund: Die Zeit selbst und insbesondere menschliche Kalendersysteme sind seltsam und hart. Letztendlich sind Zeiten und Datumsangaben keine Zeichenfolgen aus dem gleichen Grund, wie Ganzzahlen und Fließkommazahlen keine Zeichenfolgen sind, und es wird Ihr Leben nur erschweren, wenn Sie so tun, als wären es wirklich nur Anordnungen von Zeichen, weil sie es einfach nicht sind.

BrianH
quelle
26
+1 nur um das Wort heimtückisch zu gebrauchen. Ich stimme Ihren überzeugenden Argumenten und umfassenden Erklärungen zu, aber deshalb musste ich mich einloggen und für Sie stimmen.
Adrian Larson
1
Die Darstellung der Datums- / Uhrzeit als Sekunden seit einer definierten Zeit in der Vergangenheit ist auch für verschiedene Kalender robust. ZB verwenden islamische und chinesische Kalender keine der greogrianischen Monate, Jahreszahlen usw. Ich würde es als schlechte Praxis ansehen, dies auf Datenbankebene zu behandeln.
Rexkogitans
Daten werden oft als "vor X Tagen" dargestellt. Viel Glück beim Parsen auf den ursprünglichen Wert.
Agent_L
5
Vergessen wir auch nicht die DST-Änderung (und andere ähnliche) Probleme. Wird "06.11.2016 01:30:26" das erste Mal oder das zweite Mal sein, dass dieses Datum und diese Uhrzeit eintreten ? UTC DateTime ist mindestens einmalig und kann jederzeit in die lokale Darstellung für diese Zeit übersetzt werden. Eine umgekehrte Darstellung ist nicht immer möglich.
J ...
3
Why? Because it is assumed that the type provides you with lots of handy built in functionalityMeiner Meinung nach ist dies nur zweitrangig. Der wahre Grund ist, dass der Typ Ihnen sagt, was etwas ist . Ein Datum ist keine Zeichenfolge, sondern wird einfach in eine für Menschen lesbare Zeichenfolge übersetzt.
Doval
53

Er sagt, er soll den Webserver verwenden, um die Datenzeit in einen String umzuwandeln. Ich sage, mach es auf dem Datenbankserver und nicht auf dem Webserver. Warum denkst du, ist das besser? - MT Kopf

Ich möchte den Typ kennen.

Es ist mir wirklich egal, ob Ihre Datenbank Informationen in einem String, einigen Ints oder Bytes speichert, denn letztendlich sind es sowieso immer Bytes. Diese Zeichenfolge, die mehr Speicherplatz beansprucht als in Ihrer Datenbank benötigt wird, stört mich nicht. Was mich stört, sind Daten wie diese:

11/10/2016

Und nicht zu wissen, ob das der elfte oder der zehnte Monat ist.

Aber es ist bestätigt, dass Sie sagen. Sicher, Sie haben es einem Validierungsprozess unterzogen. Das Datum ist vollkommen korrekt. Aber hier behalte ich diese Sache bei und alles was ich weiß ist, dass das Datum eine Zeichenkette ist. Ich kann dir nicht mal sagen, wann das ist.

"Zehnter November im zweitausendsechzehnten Jahr unseres Herrn."

Das ist eine Saite. Eine unserer Präsentationen benötigt es in diesem Format. Sie sagten, die Datenbank konvertiert alle Daten in Zeichenfolgen, oder? Viel Spaß dabei.

Die Aufgabe der Datenbank besteht darin, Daten zu speichern, die nicht vorhanden sind. Sicher, Sie könnten das in Strings machen, aber dann müssen Sie es analysieren, um es nützlich zu machen, es für andere Formate zu präsentieren. Durch die Speicherung in einer standardmäßigen, geparsten Form für jeden Typ, den die DB anbietet, sind wir so nah an der Präsentationsbereitschaft wie möglich, ohne eine Entscheidung über die Präsentation getroffen zu haben. Es ist mir wirklich egal, ob die DB diesen Typ mit einem String oder Ints oder Bytes unterstützt. Solange es weiß, was es tut.

Wenn Sie der Datenbank jedoch nicht mitteilen, dass es sich um ein Datum handelt, und ein Datum als Zeichenfolge speichern, wird eine Präsentation vorzeitig präsentiert und allen anderen vorgezogen. Dies zwingt alle anderen Moderatoren zum Parsen, bevor sie konvertieren. Nein, die Datenbank ist kein Teil der Präsentationsschicht. Bitten Sie nicht darum.

Ebenso ist die Präsentationsschicht nicht Teil der Datenbank, sodass es nicht ratsam ist, einen Bericht mit Datenbankdetails zu koppeln. Es ist weitaus robuster, auf Typen einzuwirken.

kandierte_orange
quelle
Diese Antwort adressiert die Speicherung als Zeichenfolgen. Es wird jedoch nicht das übliche Muster zum Speichern von Datumsangaben in einem systemeigenen Datumstyp behandelt , sondern diese mit Funktionen wie CONVERT (T-SQL) in eine Zeichenfolge in der SQL-Abfrage formatiert oder dass ein DBMS normalerweise seine Datumsangaben serialisiert in eine Zeichenfolge in einem konfigurierbaren Format, unabhängig von der Abfrage. Zum Beispiel: postgresql.org/docs/9.5/static/…
dcorking
Das ist ein Bericht. Es passiert nach der Lagerung. Als würde ich mein Geburtsdatum in mein Alter umrechnen.
candied_orange
2
Ich wollte Sie lediglich ermutigen, Ihre Antwort zu erweitern, da das Thema des OP darin besteht, wie "Daten aus der Datenbankebene abgerufen werden". Es gibt ein wohlbekanntes, wenn auch wohl veraltetes Muster, bei dem ein Bericht die Datenbank nach formatierten und lokalisierten Datumszeichenfolgen abfragt. Ich denke, das OP würde diese Ablehnungsargumente gerne hören. Ich weiß, ich würde.
Dcorking
@dcorking note update.
candied_orange
+1 Hinzufügen von mehr Wasser zur Mühle: Erstellen Sie einfach ein System auf einer installierten Basis, das sich über mehrere Zeitzonen erstreckt, in denen der absolute Moment von größter Bedeutung ist, und sehen Sie, wie gut Sie mit der Konvertierung von Zeichenfolgen <-> und Zeitstempeln überall zurechtkommen. Am schlimmsten ist es, wenn die Benutzer ihre eigenen Plugins erstellen und ihnen Zeitstempel geben, da Zeichenfolgen die Konsistenz dieser Zeitstempel anzeigen.
Newtopian
19

Gebietsschema

Die Konvertierung des Datums in eine Zeichenfolge für Präsentationszwecke erfordert die Kenntnis der Benutzereinstellungen, da genau dasselbe Datum für Benutzer in verschiedenen Ländereinstellungen im Allgemeinen unterschiedlich angezeigt werden sollte. Selbst wenn Sie ein einzelnes Gebietsschema in Ihrer Anwendung verwenden, sollte bei ordnungsgemäßem Verhalten das Gebietsschema der Anwendung anstelle des Datenbankservers verwendet werden. und es ist nicht garantiert, dass sie identisch sind, auch wenn sie in diesem Moment zufällig übereinstimmen.

Die Konvertierung von einem universellen Datums-Datentyp in eine länderspezifische Zeichenfolge sollte in der Präsentationsebene erfolgen, da diese Ebene weiß, wie diese Konvertierung durchgeführt werden soll.

Peter ist
quelle
3
Stellen Sie sich vor, Sie schreiben ein Beispiel für ein nicht übereinstimmendes Gebietsschema in der Praxis für Benutzer in Maine, USA, und dann wird es in der Serverfarm an der Westküste von Amazon gehostet. ;) Das ist eigentlich gar nicht so unwahrscheinlich.
jpmc26
@ jpmc26 Ich verstehe den Unterschied nicht - verwendet Maine ein anderes Datumsformat als der Rest der USA?
Pete Kirkham
2
@PeteKirkham Maine und die Westküste der USA verwenden Zeitzonen, die 3 Stunden voneinander entfernt sind.
jpmc26
1
Oder ein anderes reales Szenario: Stellen Sie sich vor, Sie betreiben einen Server in der Schweiz, der Clients in vier (Deutsch, Französisch, Italienisch, Englisch) verschiedenen Sprachen mit unterschiedlichen Gebietsschemata (und leicht unterschiedlichen Formatierungsregeln) bedienen muss . Viel Glück bei der Auswahl des richtigen Gebietsschemas für Ihren Server in einer solchen Situation.
Voo
1
@ jpmc26 Zeitzonen und Gebietsschemas sind nicht dasselbe. Zum Beispiel haben wir Büros in Glasgow, Schottland, Atlanta, USA und Pune, Indien. Berater in diesen Büros überwachen wiederum Standorte (Campus, Krankenhäuser, Hotels usw.) weltweit rund um die Uhr. Die Anwendungsdatenbank arbeitet in UTC, zeigt jedoch die Ortszeit der überwachten Site an. Die USA-Berater haben Daten in MM / TT / JJJJ, die Ländereinstellungen für Großbritannien und Indien sind jedoch TT / MM / JJJJ - dies hängt von der Ländereinstellung und nicht von der Zeitzone der Website oder des Benutzers ab.
Pete Kirkham
9

Dies ist aus dem gleichen Grund unerwünscht, aus dem Sie keinen Typ blind in eine Zeichenfolge konvertieren möchten, sobald er die Anwendungsebene erreicht. Es ist sehr wahrscheinlich, dass Sie dieses Objekt in irgendeiner Weise verwenden möchten, bevor Sie es dem Benutzer präsentieren (wenn Sie es dem Benutzer überhaupt präsentieren). Stellen Sie sich für dieses Beispiel vor, Sie müssten eine Datumsberechnung für das Objekt durchführen. Es ist kein Nachteil, das Objekt nur in eine Zeichenfolge zu konvertieren, bevor Sie es anzeigen.

Gartenkopf
quelle
4

Typen gibt es aus einem Grund, wenn sie keinen Nutzen bringen würden, hätten wir sie nicht und würden sie nicht benutzen und hätten nur "den Typ" und alles wäre das. Sie sind nicht nur bequem, sondern tragen auch zur Sicherheit und Effizienz bei. Im Folgenden finden Sie eine Liste der Gründe, warum Sie Typen immer in ihrem ursprünglichen Format und nicht als Zeichenfolgen beibehalten sollten . Ich habe die DateTimemeiste Zeit als Beispiel verwendet, aber die gleichen Prinzipien gelten für alle primitiven Typen wie Ganzzahlen, Dezimalzahlen, Binärzahlen usw.


Datenspeicher

Einschränkungen

Geben Sie Constraint ein

In fast allen Datenspeichern können Einschränkungen für die Daten angegeben werden, einschließlich Typeinschränkungen. Einer der Hauptvorteile der Angabe einer DateTimeInstanz besteht darin, dass die gespeicherten Daten auf diesen Typ beschränkt sind. Es ist niemals möglich, etwas anderes als eine Datumszeit einzugeben, unabhängig davon, wie die Daten in den Speicher eingefügt wurden. Letzteres ist wichtig für größere Systeme, in denen mehrere Prozesse direkt mit dem Geschäft interagieren. Dies schließt auch den Versuch ein, fehlerhafte Daten wie den 30. Februar (eines Jahres) hinzuzufügen, da der Februar nur 29 Tage pro Schaltjahr und 28 Tage für Nicht-Schaltjahre haben kann.

Validierungsbeschränkungen

Es gibt auch Validierungsbeschränkungen, die im Datenspeicher implementiert werden können, z. B. das Sicherstellen, dass ein eingefügtes Datum das aktuelle Datum nicht überschreitet oder dass ein Startdatum vor einem Enddatum liegt.

Operationen

Die meisten Datenspeicher verfügen auch über integrierte Operationen / Funktionen wie DateAddoder DatePartin MS SQL Server. Auf diese Weise können Sie bestimmte Daten filtern oder auswählen, während sich die Daten noch im Speicher befinden (noch nicht in der Anwendung abgerufen).

Universell akzeptiertes Format

Durch die Verwendung des nativen Typs müssen andere Entwickler oder Systeme, die ebenfalls mit dem Speicher interagieren, nicht über die winzigen Details zum Speichern dieses primitiven Typs informiert werden. Ist dies nicht der Fall, wenn dieser Typ als Zeichenfolge gespeichert wurde, müssen Sie sicherstellen, dass jeder das Format dieser DateTimeZeichenfolgendarstellung versteht. Dieses System wird anfällig, wenn Daten verarbeitet werden, die sich über Gebietsschemata, Regionen und Kulturen des Datenursprungs, den physischen Standort einer Anwendung und die Attribute des Endbenutzers / Systems erstrecken, der mit diesen Daten interagiert. Beispiel: Das Datumsformat in einem Land könnte MM / TT / JJJJ lauten (wie in den USA), in einem anderen Land könnte es TT / MM / JJJJ lauten, sodass es fast unmöglich ist, diesen Unterschied festzustellen.

Geschwindigkeit

Die Geschwindigkeit des Abrufs, die Geschwindigkeit der Validierung, die Geschwindigkeit des Betriebs und die Speichereffizienz sind ebenfalls wichtige Faktoren. Beispiel für die Abrufgeschwindigkeit: Datenspeicher ermöglichen Indizes für Spalten, und diese Indizes können im Allgemeinen effizienter verwendet werden, wenn der Typ im systemeigenen Format gespeichert wird.

Anwendung

Datenzugriff

Das Ausführen von Abfragen für den Speicher wird mit dem systemeigenen Typsystem einfacher, da die Entwickler das Speicherformat nicht erraten müssen. Nahezu alle Datenspeicheranwendungsanbieter ( Beispiel: ado.net ) bieten Mechanismen zum Erstellen der richtigen parametrisierten Abfragen basierend auf den übergebenen nativen Typen. Hier ist ein Beispiel für das Hinzufügen des Datumsteils zu einer ado.net-Abfrage für einen SQL Server-Speicher. Dasselbe mit Strings zu tun, wäre sehr umständlich und anfällig für Fehler.

command.Parameters.Add(new SqlParameter("@startDate", SqlDbType.Date) {Value = myDateInstance.Date});

Operationen

Die systemeigenen Codetypen bieten auch Standardvorgänge wie den .NET-Typ System.Date. Operationen sind normalerweise mathematischer Natur wie das Hinzufügen von Datumsangaben, das Ermitteln des Unterschieds zwischen Datumsangaben usw. Auch dies ist bei Zeichenfolgentypen nicht einfach möglich.

Präsentationsfolie

Gebietsschema

Wenn ein primitiver Typ schließlich in eine Zeichenfolge in der Präsentationsebene konvertiert wird ( die richtige Position im Programmstapel, um dies zu tun ), hat der Programmierer jetzt verschiedene Optionen, um ihn entsprechend dem Kontext, in dem er dargestellt wird, korrekt anzuzeigen. Dieser Kontext besteht im Allgemeinen aus der tatsächlichen Bedeutung der Daten und dem Gebietsschema des Benutzers.

Beispiel 1

Eine datetime-Instanz kann basierend auf dem Gebietsschema des Benutzers automatisch formatiert werden.

DateTime.Now.ToString("D", CultureInfo.GetCultureInfo(userContext.Culture))
Beispiel 2

Eine Dezimalinstanz könnte einen Betrag (eine Währung) darstellen, und das Gebietsschema des Benutzers sollte dann auch den Betrag entsprechend seiner Präferenz anzeigen. Eine c # -Anwendung zeigt den Wert dann möglicherweise mit an

amount.ToString("C", CultureInfo.GetCultureInfo(userContext.Culture))

Dies kann kritisch sein, da verschiedene Kulturen unterschiedliche Zahlen anzeigen. In den USA haben Punkt (.) Und Komma (,) genau die umgekehrte Bedeutung wie in den Niederlanden.

Lage

Dies ist sehr DateTimeinstanzspezifisch. Ein Datum und eine Uhrzeit stellen ein Ereignis zu einem bestimmten Zeitpunkt dar, dies muss dem Benutzer jedoch in der Regel in Abhängigkeit von seiner eigenen Zeitzone mitgeteilt / präsentiert werden. Beispiel: Eine DateTimeInstanz 2016-09-21T23:38:21.399Zkönnte wie 9/21/2016 5:21 PMfür einen Benutzer in der östlichen Zeitzone in den USA angezeigt werden . Es gibt viele Möglichkeiten, dies zu erreichen, aber es wird nahezu unmöglich, wenn die Datums- / Uhrzeitinstanz als Zeichenfolgentyp oder im Datenspeicher als Zeichenfolgentyp gespeichert wird.


Allgemeine Regel

Die beiden allgemeinen Regeln für eine Anwendung beim Konvertieren eines primitiven Typs in eine Zeichenfolgendarstellung lauten wie folgt

  • Wenn Sie Eingaben akzeptieren, konvertieren Sie diese Eingaben so früh wie möglich in den richtigen primitiven Typ im Programmstapel (normalerweise in der Präsentationsebene).
  • Konvertieren Sie diese Daten beim Abrufen der anzuzeigenden Daten so spät wie möglich in die Zeichenfolgendarstellung im Programmstapel (ebenfalls in der Regel in der Präsentationsebene).
Igor
quelle
0

Es ist wirklich nichts Falsches daran (dies wird bei Diensten ständig durchgeführt), solange Sie ein nicht mehrdeutiges Format für Ihr Datum verwenden. Mit eindeutig meine ich, dass nicht nur das Datum klar ist (z. B. MM / DD vs. DD / MM), sondern auch die Zeitzone, in der es sich befindet. Wenn Sie also Ihre Daten als Text darstellen möchten, verwenden Sie im Voraus ein ISO-Format . Ich bevorzuge UTC-basierte Zeitzeichenfolgen.

Vorteile:

  • Auf Standards basierende Datums- / Uhrzeit-Zeichenfolgen sind portabel und leicht zu verstehen
  • Häufig enthalten Daten in DBs eine Zeitkomponente. Wenn dies für Ihre Daten nicht von Bedeutung ist, kann dies die Dinge tatsächlich vereinfachen.

Nachteile:

  • Datengröße. Das interne Format eines Datums in einer Datenbank benötigt im Allgemeinen viel weniger Speicherplatz als das String-Rendering dieses Datums.
  • In der Regel möchten Sie eine echte Datums- oder Zeitstruktur auf dem Client erstellen, damit das Parsen möglicherweise länger dauert.

Wenn jemand sagte, er wolle das tun, würde ich fragen: "Warum?" weil es nicht wirklich viel Sinn macht. Wenn jemand das Datum als Zeichenfolge zurückgeben möchte, weil er es nur direkt anzeigt, ist dies kein guter Grund, Zeichenfolgen aus der Datenbank zu verwenden.

JimmyJames
quelle