我的C#winforms计划将在以下国家/地区使用
United Kingdom : date format day-month-year , currency separator is '.'
United States : date format month-day-year , currency separator is '.'
Denmark : date format day-month-year , currency separator is ','
无论用户计算机上的区域设置如何,我都希望程序正常运行。我主要关注的是处理日期格式和货币字段 (语言翻译不是问题,因为程序只会显示英文文本)
为此,我决定数据库中的所有日期将以yyyy-mm-dd
格式保存,所有小数字段将以.
作为分隔符保存。
我使用Danish_Norwegian_CI_AS
排序规则创建了数据库。
所以我假设数据将以上述datetime
格式保存。十进制格式,没有我要求做任何特殊的事情。
我已在程序中添加以下代码
var cult = new CultureInfo("en-GB");
Thread.CurrentThread.CurrentCulture = cult;
Thread.CurrentThread.CurrentUICulture = cult;
CultureInfo.DefaultThreadCurrentCulture = cult;
CultureInfo.DefaultThreadCurrentUICulture = cult;
请根据您的经验告诉我上述代码是否足以使我的程序安全
答案 0 :(得分:2)
文化仅在以下两种情况下应用 :
将值的字符串表示形式转换为本机格式,称为"解析"。
将值的原生格式转换为字符串表示形式,称为"格式化"。
将datetime
或decimal
或其他类型存储到数据库中时,它将以本机格式存储。在SQL数据库中,这通常是一些您永远不会直接使用的紧凑二进制值。
考虑以下SQL:
declare @dt datetime
set @dt = '01/02/2015 12:34:56'
select @dt
在第一行中,我们声明了一个datetime
类型的变量。它不是一个字符串,它是一个占用8个字节内存或磁盘的特定数据类型。
在第二行中,我们为变量分配一个字符串值。 SQL 解析字符串,将其转换为datetime
,以便将其存储在@dt
变量中。存储的实际值具有0x0000A41400CF5940
的十六进制表示。
在进行解析时,应用了运行代码的环境的当前文化。因为我在美国,它将日期解释为1月2日。如果我在欧洲,它会将日期解释为2月1日(将内部值更改为0x0000A43200CF5940
)。
使用yyyy-mm-dd
格式的日期可避免误解,但这并不意味着实际值存储为该格式的字符串。只是格式是明确的,所以无论文化如何,它都将以相同的方式解析。
在上面的第三行代码中,我们选择变量以将其包含在结果集中。虽然我们在没有任何转换的情况下以原生形式选择它,但我们最终以字符串表示形式查看它。如果在SQL Server Management Studio等工具中运行查询,则输出窗口将格式化本地值为字符串,以便您可以读取它们。这样做时,再次应用当前的文化。 SQL的默认设置是以yyyy-mm-dd
格式显示日期,而不是特定于文化的格式。但是其他值(例如小数)将使用当前文化的分隔符。
如果不是在SSMS中运行它,而是通过SqlDataReader
中的自己的代码实际检索结果(例如),那么格式化永远不会发生。读者使用the mappings shown here将SQL的二进制本机值直接映射到适当的.NET本机类型。 SQL datetime
本机映射到.NET DateTime
。
DateTime dt = (DateTime) reader["dt"];
现在很多时候,你会看到有人做这样愚蠢的事情:
DateTime dt = Convert.ToDateTime(reader["dt"].ToString());
这很浪费,因为值已经一个DateTime
,并且此代码将使用当前区域性格式化字符串,然后再次使用它来解析字符串。无缘无故地进行了大量的字符串操作。
最终,在您的.NET代码中,您将最终使用该DateTime
值并将其转换为某个字符串以进行输出。当你这样做时,当你应用当前文化时 。
同样,当您收到用户的输入字符串时(例如填写表单时),您再次使用当前文化将值解析为DateTime
。
原生数据类型不是字符串 - 因此不受文化影响。
注意:
如果要查看任何SQL数据类型的本机二进制形式的十六进制表示形式,可以使用以下内容:select convert(varbinary, @dt)
请注意您工作的任何地方的原生格式。如果您正在写入http流,文本文件或文档数据库等,字符串表示确实确实很重要,因为字符串 这些场景中的原生格式。
为了证明这不仅适用于日期,请考虑:
select 123, 123.45, convert(varbinary, 123), convert(varbinary, 123.45)
--results: 123 123.45 0x0000007B 0x0502000139300000