在典型的Web应用程序中,从强类型的数据库层中检索日期(例如,在c#中为System.DateTime,与System.String相反)。
当日期需要表示为字符串时(例如,显示在页面上),则在表示层中完成从DateTime到字符串的转换。
为什么是这样?为什么将DateTime转换为数据库层上的字符串是一件坏事?
在典型的Web应用程序中,从强类型的数据库层中检索日期(例如,在c#中为System.DateTime,与System.String相反)。
当日期需要表示为字符串时(例如,显示在页面上),则在表示层中完成从DateTime到字符串的转换。
为什么是这样?为什么将DateTime转换为数据库层上的字符串是一件坏事?
Answers:
日期,日期时间以及实际上任何其他类型的对象,通常应保留其正确类型的格式,直到需要将它们转换为其他类型的时间为止-尤其是当该类型是人类可读的形式时,尤其是当它是有损/单向转换。
为什么?因为假定类型为您提供了许多方便的内置功能,例如适当的相等性测试,加法和减法,比较(大于,小于),时区和语言环境功能(对于与时间相关的任何事物尤其重要),等等。如果您决定要支持美国人和“ Month Day [th],Year”格式,以及常见的英式“ Day Month Year”,还是ISO标准“ Year-Month-Day”?如果它是字符串并且需要进行更改并将其解析回Date,该怎么办?gh,不,谢谢-这样会有很多弊端和臭虫,最好完全避免。
更具体地说,您提到了分层体系结构,该体系结构的表示层与稍后的数据分开。这实际上是将Date作为日期而不是字符串传递的另一个重要原因-因为该日期应放入哪种类型的字符串格式中?您是否要稍后在日期字段上对英文,中文(带或不带秒/毫秒,完整的月份名称或数字)进行排序(对字符串进行排序需要某种字符串格式,如果您希望它能正常工作的话)等等?这完全是表示的问题-用户应如何查看数据-并将该逻辑放置在其他任何地方将首先限制分层体系结构的优势。数据库不需要知道或关心将来如何查看日期。
最后,几乎所有关心时间的复杂应用程序(这是分层体系结构的目的)都将不可避免地以许多不同方式(通常在体系结构的所有不同级别)使用时间/日期。存在与时间和日期相关的类型化对象的确有充分的理由:时间本身,尤其是人类日历系统,既奇怪又困难。最终,时间和日期不是字符串,其原因与整数和浮点数不是字符串一样,并且如果您假装它们实际上只是字符数组,只会使您的生活更加艰难,因为它们不是字符数组。
Why? Because it is assumed that the type provides you with lots of handy built in functionality
我认为这只是次要的。真正的原因是类型告诉您什么是什么。日期不是字符串,它只是很容易转换为人类可读的字符串。
他说要使用Web服务器将数据时间转换为字符串。我是说在数据库服务器而不是Web服务器上执行此操作。您为什么认为更好?- MT头
我想知道类型。
我真的不在乎您的数据库是否将信息存储在字符串,一些整数或字节中,因为最后,无论如何它始终是字节。该字符串所占用的空间超过了数据库所需的空间,这并不困扰我。令我困扰的是这样的日期:
2016年11月10日
而且不知道是第十一个月还是第十个月。
但是您说的已经过验证。确保您通过了验证过程。日期是完全正确的。但是在这里我维护着这个东西,我只知道日期是一个字符串。我什至不告诉你这是几号。
“我们主人在二千一十六年的十一月第十日。”
那是一个字符串。我们的演示文稿之一需要这种格式。您说数据库将所有日期都转换为字符串,对吗?玩得开心。
数据库的工作是存储数据而不是现有数据。当然,您可以在字符串中执行此操作,但随后必须对其进行解析,以使其对于其他格式的呈现很有用。以标准的解析形式将其存储到数据库提供的任何类型,都可以使我们尽可能地准备好呈现,而无需做出呈现决定。对于我来说,数据库是否使用字符串,整数或字节支持该类型真的不重要。只要知道它在做什么。
但是,当您不让数据库知道我们正在处理一个日期并将日期存储为字符串时,您会过早地呈现该表述,并且优先于其他所有表述。这迫使所有其他演示者在转换之前进行解析。不,数据库不是表示层的一部分。不要问它是。
同样,表示层也不是数据库的一部分,因此将报表与数据库详细信息耦合也是不明智的。对类型进行操作要健壮得多。
为了演示目的,将日期转换为字符串需要了解用户的喜好,因为对于不同地区的用户,通常应该完全相同地显示同一日期。即使您在应用程序中使用单个语言环境,正确的行为也应使用应用程序的语言环境而不是数据库服务器。并且即使此时恰好匹配,也不能保证它们是相同的。
从通用日期数据类型到特定于语言环境的字符串的转换应该在表示层中进行,因为它是知道如何执行转换的层。
类型的存在是有原因的,如果它们没有带来任何好处,那么我们将不会拥有它们,也不会使用它们,而我们只会拥有“类型”,而一切都会如此。它们不仅方便,还增加了安全性和效率。以下列出了为什么您应始终以其本机格式而不是字符串形式保留类型。我DateTime
大部分时间都作为示例,但是相同的原理适用于任何原始类型,例如整数,小数,二进制等。
几乎所有数据存储区都允许指定数据约束,其中包括类型约束。指定DateTime
实例的主要好处之一是将存储的数据限制为该类型。无论日期如何插入到存储中,都永远不可能输入除日期时间以外的任何内容。后者对于大型系统非常重要,在大型系统中,有多个与商店直接交互的流程。这还包括尝试添加错误的日期(例如每年的2月30日),因为2月February年只能有29天,非non年只能有28天。
还可以在数据存储区中实施验证约束,例如确保插入的日期不超过当前日期或开始日期早于结束日期。
大多数数据存储区还具有内置的操作/功能,例如DateAdd
或DatePart
在MS Sql Server中。这样,您就可以在数据仍在存储中(尚未检索到应用程序)时开始过滤或选择特定数据。
通过使用本机类型,也不必通知其他与商店交互的开发人员或系统有关该原始类型如何存储的详细信息。如果该类型存储为字符串则不是这种情况,那么您必须确保每个人都理解该DateTime
字符串表示形式的格式。当处理跨越数据来源中的区域,区域和区域性的数据,应用程序的物理位置以及与该数据进行交互的最终用户/系统的属性时,此系统变得脆弱。例如:一个国家的日期格式可能是MM / dd / yyyy(例如在美国),但在另一个国家中,日期格式可能是dd / MM / yyyy,因此几乎不可能检测到这种差异。
检索速度,验证速度,操作速度和存储效率都是重要因素。检索速度的示例:数据存储允许在列上进行索引,并且如果以本机格式存储类型,则通常可以更有效地使用这些索引。
使用本机类型系统,对商店执行查询变得更加简单,因为开发人员再次不必猜测存储格式。几乎所有的数据存储应用程序提供程序(例如:ado.net)都提供了用于根据传入的本机类型创建适当的参数化查询的机制。这是将Date部分添加到针对Sql Server存储的ado.net查询中的示例,对字符串执行相同的操作将非常麻烦且容易出错。
command.Parameters.Add(new SqlParameter("@startDate", SqlDbType.Date) {Value = myDateInstance.Date});
代码中的本机类型还提供标准操作,例如.net类型System.Date
。操作通常本质上是数学的,例如添加日期,查找日期之间的差异等。同样,在字符串类型上也不容易做到这一点。
当原始类型最终在表示层(在程序堆栈中的正确位置)中转换为字符串时,程序员现在可以使用各种选项来根据显示上下文正确地显示它。该上下文通常由数据的实际含义和用户的语言环境组成。
例子1可以基于用户的语言环境自动格式化日期时间实例。
DateTime.Now.ToString("D", CultureInfo.GetCultureInfo(userContext.Culture))
例子2
十进制实例可以表示金额(货币),然后用户的语言环境还应根据其偏好显示金额。然后,C#应用程序可能会使用
amount.ToString("C", CultureInfo.GetCultureInfo(userContext.Culture))
这可能很关键,因为不同的文化显示数字的方式不同。在美国,句号(。)和逗号(,)与荷兰的含义完全相反。
这是非常特定于DateTime
实例的。日期和时间表示在特定时间点发生的事件,但是通常必须根据用户自己的时区将其传达/呈现给用户。示例:可以在美国东部时区为用户显示一个DateTime
实例。有很多方法可以完成此操作,但如果日期时间实例以字符串类型保存在内存中或以字符串类型保存在数据存储中,则几乎无法实现。2016-09-21T23:38:21.399Z
9/21/2016 5:21 PM
在将任何原始类型转换为字符串表示形式时,应遵循应用程序的一般2条规则,这些规则如下:
只要您在日期中使用无歧义的格式,这样做就没有任何问题(服务中一直都在这样做)。明确地说,我的意思是不仅要明确日期(例如MM / DD vs. DD / MM),而且要明确其所在的时区。因此,在开始时,如果要将日期表示为文本,请使用ISO格式。我非常喜欢基于UTC的时间字符串。
优点:
缺点:
如果有人说他们想这样做,我会问“为什么?” 因为没有太多意义。如果有人要返回日期作为字符串的原因是因为他们只是直接显示日期,那么这不是从数据库中使用字符串的好理由。