使用其他区域性时错误的 DateTime 解析
Wrong DateTime parsing when using other cultures
我在多语言站点中使用 EF 将结果从 SP 映射到对象。
ctx.Database.SqlQuery<MyDTO>("MySP {0}", Id).SingleOrDefault()
我看到当文化发生变化时映射日期存在问题。
更具体地说,根据用户文化,我得到与 16/12/2015 09:06:15
或 12/16/2015 09:06:15
相同的日期。
我知道两个解决方案:
- 获取字符串形式的日期并用
CultureInfo.InvariantCulture
解析它。
- 在调用存储库方法之前将文化切换到
CultureInfo.CultureInvariant
。
也许还有另一种选择:
- 我看到我们将
Thread.CurrentThread.CurrentUICulture
和 Thread.CurrentThread.CurrentCulture
都更改为用户的语言环境,但我认为我们应该只切换 UI 一个。但是我不确定如果我改变这个会破坏什么...
有没有其他选择,比如在 EF 上下文中设置区域性?
更新:
在进行查询之前更改 Thread.CurrentThread.CurrentUICulture
和 Thread.CurrentThread.CurrentCulture
似乎也无济于事。这令人困惑......也许 EF 在较早的时候缓存了文化?
首先,您应该避免那样调用存储过程 - 这是解决 OWASP Top 10 Sql 注入安全问题的简单方法。
相反,您应该通过将参数作为实际参数传递给存储过程来调用,例如:
string dateAsString = "12/16/2015 09:06:15";
string dateFormat = "MM/dd/yyyy HH:mm:ss";
DateTime theValue = DateTime.Parse(dateAsString, dateFormat, CultureInfo.InvariantCulture);
SqlParameter myDate = new SqlParameter("@theDate", theValue);
context.Database.ExecuteSqlCommand("MySP @theDate", theDate);
您可以将日期时间存储为长(柚木)或实数(将日期时间转换为实数时得到的数字)。然后您可以将这些值无任何损失地转换为任何文化。
我终于弄明白了。 :)
我正在查看手表中 DateTime
的值。这实际上是问题所在......看起来手表使用当前线程的文化(从而将月份和日期的顺序从文化切换到文化)。事实证明日期是正确的(如果您认为 16 是月份,那么 12/16/2015 09:06:15
无论如何都不是有效日期...意识到这一点永远不会太晚...)。
所以,VS 观察者迷惑了我...
很高兴知道当前的线程文化不会影响 SQL 数据的解析,正如我所期望的那样。 :)
实际的错误出现在稍后的代码中。
我在多语言站点中使用 EF 将结果从 SP 映射到对象。
ctx.Database.SqlQuery<MyDTO>("MySP {0}", Id).SingleOrDefault()
我看到当文化发生变化时映射日期存在问题。
更具体地说,根据用户文化,我得到与 16/12/2015 09:06:15
或 12/16/2015 09:06:15
相同的日期。
我知道两个解决方案:
- 获取字符串形式的日期并用
CultureInfo.InvariantCulture
解析它。 - 在调用存储库方法之前将文化切换到
CultureInfo.CultureInvariant
。
也许还有另一种选择:
- 我看到我们将
Thread.CurrentThread.CurrentUICulture
和Thread.CurrentThread.CurrentCulture
都更改为用户的语言环境,但我认为我们应该只切换 UI 一个。但是我不确定如果我改变这个会破坏什么...
有没有其他选择,比如在 EF 上下文中设置区域性?
更新:
在进行查询之前更改 Thread.CurrentThread.CurrentUICulture
和 Thread.CurrentThread.CurrentCulture
似乎也无济于事。这令人困惑......也许 EF 在较早的时候缓存了文化?
首先,您应该避免那样调用存储过程 - 这是解决 OWASP Top 10 Sql 注入安全问题的简单方法。
相反,您应该通过将参数作为实际参数传递给存储过程来调用,例如:
string dateAsString = "12/16/2015 09:06:15";
string dateFormat = "MM/dd/yyyy HH:mm:ss";
DateTime theValue = DateTime.Parse(dateAsString, dateFormat, CultureInfo.InvariantCulture);
SqlParameter myDate = new SqlParameter("@theDate", theValue);
context.Database.ExecuteSqlCommand("MySP @theDate", theDate);
您可以将日期时间存储为长(柚木)或实数(将日期时间转换为实数时得到的数字)。然后您可以将这些值无任何损失地转换为任何文化。
我终于弄明白了。 :)
我正在查看手表中 DateTime
的值。这实际上是问题所在......看起来手表使用当前线程的文化(从而将月份和日期的顺序从文化切换到文化)。事实证明日期是正确的(如果您认为 16 是月份,那么 12/16/2015 09:06:15
无论如何都不是有效日期...意识到这一点永远不会太晚...)。
所以,VS 观察者迷惑了我...
很高兴知道当前的线程文化不会影响 SQL 数据的解析,正如我所期望的那样。 :)
实际的错误出现在稍后的代码中。