web-dev-qa-db-fra.com

Pourquoi ne pas renvoyer les dates sous forme de chaîne de la base de données?

Dans une application Web typique, les dates sont extraites de la couche de base de données fortement typées (par exemple en c # en tant que System.DateTime par opposition à System.String).

Lorsqu'une date doit être exprimée sous forme de chaîne (par exemple affichée sur une page), la conversion de DateTime en chaîne se fait dans le niveau de présentation.

Pourquoi est-ce? Pourquoi est-ce une mauvaise chose de convertir le DateTime en une chaîne au niveau de la base de données?

Voir aussi le débat animé dans le chat , et le question d'origine qui a commencé tout cela .

41
John Wu

Les dates, DateTimes et tout autre objet typé doivent généralement être laissés dans leur format correctement tapé jusqu'au moment où vous en avez besoin pour en faire un autre type - en particulier lorsque ce type est une forme lisible par l'homme, et en particulier lorsqu'il s'agit d'une conversion à perte/à sens unique.

Pourquoi? Parce qu'il est supposé que le type vous offre de nombreuses fonctionnalités intégrées pratiques, comme les tests d'égalité appropriés, l'addition et la soustraction, la comparaison (supérieure à, inférieure à), le fuseau horaire et les fonctionnalités locales (particulièrement importantes pour tout ce qui concerne le temps), etc. Si vous décidez de soutenir les Américains et le format "Month Day [th], Year" ainsi que le style britannique commun de "Day Month Year", ou la norme ISO "Year-Month-Day"? Que feriez-vous s'il s'agissait d'une chaîne et que vous deviez faire ce changement, le réanalyser en une date? Ugh, non merci - il y a beaucoup de maux et de bogues ignobles de cette façon, qu'il vaut mieux éviter complètement.

Plus précisément, vous avez mentionné l'architecture à plusieurs niveaux, dont la couche de présentation est distincte des données ultérieurement. C'est en fait l'autre grande raison de passer une date en tant que date et non en tant que chaîne - car dans quel type de formatage de chaîne la date doit-elle être insérée? Anglais, chinois, avec ou sans secondes/millisecondes, nom complet du mois ou chiffres, voudrez-vous trier plus tard sur le champ de date (le tri sur une chaîne requiert un certain format de chaîne si vous voulez que cela fonctionne correctement), etc.? Tout cela est une question de présentation - comment l'utilisateur doit voir les données - et placer cette logique ailleurs limiterait l'avantage d'avoir une architecture à plusieurs niveaux en premier lieu. La base de données ne devrait pas avoir besoin de savoir ou de savoir comment vous souhaitez afficher la date à l'avenir.

Enfin, presque toutes les applications complexes (c'est à cela que servent les architectures à plusieurs niveaux) qui se soucient du temps utiliseront inévitablement les heures/dates de nombreuses façons, et souvent à tous les niveaux de l'architecture. Les objets typés liés aux heures et aux dates existent pour une très bonne raison: le temps lui-même, et en particulier les systèmes de calendrier humains, sont étranges et difficiles. En fin de compte, les heures et les dates ne sont pas des chaînes pour la même raison que les entiers et les virgules flottantes ne sont pas des chaînes, et cela ne vous rendra la vie plus difficile si vous essayez de prétendre qu'il ne s'agit en réalité que de tableaux de caractères, car ils ne le sont tout simplement pas.

168
BrianH

Il dit d'utiliser le serveur Web pour convertir le temps des données en chaîne. Je dis de le faire sur le serveur de base de données et non sur le serveur Web. Pourquoi pensez-vous que c'est mieux? - Tête M T

Je veux connaître le type.

Je ne me soucie vraiment pas si votre base de données stocke des informations dans une chaîne, quelques octets ou octets, car, au final, ce sont toujours des octets de toute façon. Cette chaîne prenant plus d'espace que nécessaire dans votre base de données ne me dérange pas. Ce qui me dérange, c'est de rencontrer des dates comme celle-ci:

10/11/2016

Et ne sachant pas si c'est le onzième mois ou le dixième mois.

Mais c'est validé, dites-vous. Bien sûr, vous l'avez soumis à un processus de validation. La date est parfaitement correcte. Mais ici, je maintiens cette chose et tout ce que je sais, c'est que la date est une chaîne. Je ne peux même pas vous dire à quelle date il s'agit.

"Le 10 novembre de l'an deux mille seizième de notre seigneur."

Voilà une chaîne. Une de nos présentations en a besoin dans ce format. Vous avez dit que la base de données convertit toutes les dates en chaînes, n'est-ce pas? Amusez-vous avec ça.

Le travail de la base de données consiste à stocker des données qui ne sont pas présentes. Bien sûr, vous pouvez le faire en chaînes mais vous devez ensuite l'analyser pour le rendre utile à présenter pour d'autres formats. Le stockage sous une forme standard analysée pour tout type de la DB offre nous permet d'être aussi prêt à présenter que possible sans avoir pris une décision de présentation. Peu m'importe vraiment si la base de données sauvegarde ce type avec une chaîne ou des entiers ou des octets. Tant qu'il sait ce qu'il fait.

Mais lorsque vous ne laissez pas la base de données savoir que nous avons affaire à une date et que vous stockez une date sous forme de chaîne, vous présentez prématurément et privilégiez une présentation par rapport à toutes les autres. Cela oblige tous les autres présentateurs à analyser avant de convertir. Non, la base de données ne fait pas partie de la couche de présentation. Ne le demandez pas.

De même, la couche de présentation ne fait pas partie de la base de données, il n'est donc pas judicieux de coupler un rapport aux détails de la base de données. Il est beaucoup plus robuste d'agir sur les types.

53
candied_orange

Lieu

La conversion de la date en chaîne à des fins de présentation nécessite de connaître les préférences de l'utilisateur, car la même date exacte doit généralement être affichée différemment pour les utilisateurs dans différents paramètres régionaux. Même si vous utilisez un seul environnement local dans votre application, un comportement approprié doit utiliser l'environnement local de application au lieu du serveur de base de données; et ils ne sont pas garantis identiques même si à ce moment ils correspondent par coïncidence.

La conversion d'un type de données de date universelle en une chaîne spécifique aux paramètres régionaux doit se produire dans la couche de présentation, car c'est la couche qui sait comment que la conversion doit être effectuée.

19
Peteris

Ceci n'est pas souhaitable pour la même raison que vous ne voudriez pas simplement convertir aveuglément le type any en chaîne dès qu'il atteint le niveau application. Il est fort probable que vous souhaitiez utiliser cet objet d'une certaine manière avant de le présenter à l'utilisateur (si vous le présentez même à l'utilisateur). Pour cet exemple spécifique, imaginez que vous deviez faire un calcul de date sur l'objet. Il n'y a aucun inconvénient à simplement convertir l'objet en chaîne précisément avant de l'afficher.

9
gardenhead

Les types existent pour une raison, s'ils n'apportaient aucun avantage, alors nous ne les aurions pas et ne les utiliserions pas et nous aurions simplement "le type" et tout serait ça. Ils ne sont pas seulement pratiques, ils ajoutent également sécurité et efficacité. Voici une liste des raisons pour lesquelles vous devez toujours conserver les types dans leur format natif et non sous forme de chaînes. J'ai utilisé DateTime comme exemple la plupart du temps, mais les mêmes principes s'appliquent à tout type primitif comme les nombres entiers, décimaux, binaires, etc.


Magasin de données

Contraintes

Contrainte de type

Presque tous les magasins de données permettent de spécifier des contraintes sur les données, cela inclut les contraintes de type. L'un des principaux avantages de la spécification d'une instance DateTime est que les données stockées seront limitées à ce type. Il ne sera jamais possible de saisir autre chose qu'une date et heure quelle que soit la façon dont les données ont été insérées dans le magasin. Ce dernier est important pour les grands systèmes où il existe plusieurs processus qui interagissent directement avec le magasin. Cela inclut également d'essayer d'ajouter des dates erronées comme le 30 février (de n'importe quelle année), car février ne peut avoir que 29 jours sur une année bissextile et 28 jours pour les années non bissextiles.

Contraintes de validation

Il existe également des contraintes de validation qui peuvent être implémentées dans le magasin de données, comme garantir qu'une date insérée ne dépasse pas la date actuelle ou qu'une date de début se produit avant une date de fin.

Les opérations

La plupart des magasins de données ont également intégré des opérations/fonctions telles que DateAdd ou DatePart dans MS SQL Server. Cela vous permet de commencer à filtrer ou à sélectionner des données spécifiques pendant que les données sont toujours dans le magasin (pas encore récupérées dans l'application).

Format universellement accepté

En utilisant le type natif, d'autres développeurs ou systèmes qui interagissent également avec le magasin n'ont pas à être informés des moindres détails de la façon dont ce type primitif est stocké. Ce n'est pas le cas si ce type a été stocké sous forme de chaîne, vous devez vous assurer que tout le monde comprend le format de cette représentation de chaîne DateTime. Ce système devient fragile lorsqu'il s'agit de données couvrant des paramètres régionaux, régionaux et culturels dans l'origine des données, l'emplacement physique d'une application et les attributs de l'utilisateur final/système qui interagit avec ces données. Exemple: le format de la date dans un pays peut être MM/jj/aaaa (comme aux États-Unis) mais dans un autre, il peut être jj/MM/aaaa, détecter cette différence devient presque impossible.

La vitesse

La vitesse de récupération, la vitesse de validation, la vitesse des opérations et l'efficacité du stockage sont également des facteurs importants. Exemple de vitesse de récupération: les magasins de données permettent des index sur les colonnes et ces index peuvent généralement être utilisés plus efficacement si le type est stocké dans son format natif.

Application

Accès aux données

L'exécution de requêtes sur le magasin devient plus simple en utilisant le système de type natif, car les développeurs, une fois de plus, n'ont pas à deviner le format de stockage. Presque tous les fournisseurs d'applications de stockage de données (exemple: ado.net) fournissent des mécanismes pour créer les requêtes paramétrées appropriées en fonction des types natifs transmis. Voici un exemple d'ajout de la partie Date à un ado.net requête contre un magasin Sql Server, faire de même avec des chaînes serait très lourd et fragile/sujet aux erreurs.

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

Les opérations

Les types natifs dans le code permettent également des opérations standard comme le type .net System.Date. Les opérations sont généralement de nature mathématique comme l'ajout de dates, la recherche de la différence entre les dates, etc. Encore une fois, il n'est pas possible de le faire facilement sur les types de chaîne.

Couche de présentation

Lieu

Lorsqu'un type primitif est finalement converti en une chaîne dans la couche de présentation (l'emplacement correct dans la pile du programme pour le faire) le programmeur a maintenant diverses options pour l'afficher correctement en fonction du contexte dans lequel il est présenté. Ce contexte se compose généralement de la signification réelle des données et des paramètres régionaux de l'utilisateur.

Une instance datetime peut être automatiquement formatée en fonction des paramètres régionaux de l'utilisateur.

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

Une instance décimale pourrait représenter un montant (devise) et les paramètres régionaux de l'utilisateur devraient également afficher le montant selon leur préférence. Une application c # peut alors afficher la valeur en utilisant

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

Cela pourrait être critique car les différentes cultures affichent les nombres différemment. Aux États-Unis, la période (.) Et la virgule (,) ont exactement le même sens qu'aux Pays-Bas.

Emplacement

Ceci est très spécifique aux instances DateTime. Une date et une heure représentent une occurrence à un moment précis mais cela doit généralement être transmis/présenté à l'utilisateur en fonction de son propre fuseau horaire. Exemple: une instance de DateTime2016-09-21T23:38:21.399Z pourrait s'afficher comme 9/21/2016 5:21 PM pour un utilisateur du fuseau horaire oriental aux États-Unis. Il existe de nombreuses façons d'accomplir cela, mais cela devient presque impossible si l'instance de date-heure est conservée en mémoire en tant que type de chaîne ou dans le magasin de données en tant que type de chaîne.


Règle générale

Les 2 règles générales d'une application à suivre pour convertir tout type primitif en une représentation sous forme de chaîne sont les suivantes.

  • Lorsque vous acceptez une entrée, convertissez cette entrée dans le bon type de primitive le plus tôt possible dans la pile de programmes (généralement dans la couche de présentation)
  • Lors de la récupération des données à afficher, convertissez ces données en représentation sous forme de chaîne le plus tard possible dans la pile du programme (là encore, généralement dans la couche de présentation)
4
Igor

Il n'y a vraiment rien de mal à faire cela (cela se fait tout le temps dans les services) tant que vous utilisez un format non ambigu pour votre date. Par univoque, je veux dire non seulement la date est claire (par exemple MM/DD vs DD/MM) mais aussi le fuseau horaire dans lequel elle se trouve. Donc, dès le départ, si vous voulez représenter vos dates sous forme de texte, utilisez un format ISO . Je préfère fortement les chaînes de temps basées sur UTC.

Avantages:

  • Date/heure basées sur des normes Les chaînes sont portables et faciles à comprendre
  • Souvent, les dates dans les bases de données contiennent une composante horaire. Si cela n'a pas de sens pour vos données, cela peut en fait simplifier les choses.

Les inconvénients:

  • Taille des données. Le format interne d'une date dans une base de données utilise généralement beaucoup moins d'espace que le rendu String de cette date.
  • Vous souhaiterez généralement l'intégrer dans une structure de date ou d'heure réelle sur le client afin qu'il puisse y avoir du temps supplémentaire dans l'analyse.

Si quelqu'un disait qu'il voulait faire ça, je demanderais "pourquoi?" parce qu'il n'y a pas vraiment de point à cela. Si la raison pour laquelle quelqu'un souhaite renvoyer la date sous forme de chaîne est parce qu'ils l'afficheront directement, ce n'est pas une bonne raison d'utiliser des chaînes de la base de données.

0
JimmyJames