C#和SQL数据库的区域问题

时间:2010-03-10 14:45:43

标签: c# sql-server datetime

根据我所知的确切区域设置,为什么dateTimePicker.Value.Date.ToShortDateString();在Windows 7 x64 PL,Windows Vista x32 PL和Windows XP PL上的行为会有所不同。在进入数据库之前,我发现了这种转换的难点。

它在Windows 7(我的开发机器),同事VISTA系统上工作正常,但它无法在Windows XP上运行(白天一直用月切换)。同样在更高的系统上,我们在ListView上显示了2010-01-13,而在他的系统上,他有13-01-2010。

我想在我的旧代码中我可能有更多的类型转换,我将不得不通过并验证它,但我想知道为什么它在相同的区域设置上表现如此。我想我永远不应该做那样的转换,但是经过很长一段时间工作正常后,我已经很难学会了。

编辑:

我这样使用它(注释掉导致麻烦的代码)。回到过去,我认为ToShortDateString是确保在没有Time的情况下将其放入DB的唯一方法(因为我正在阅读DateTimePicker)。我现在知道我应该在DateTimePicker上使用.Date,但我现在更加聪明,因为它确实炸毁了我。这是代码:

    private static void sqlWpiszDaneSwieta(DateTime varData, string varDataNazwa) {
        //string varDataSwieto = varData.ToShortDateString();
        const string preparedCommand = @"INSERT INTO [dbo].[TypyDatySwiat]
                                           ([SwietaData]
                                           ,[SwietaNazwa])
                                     VALUES
                                           (@varData
                                           ,@varDataNazwa)";
          using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails))
        using (SqlCommand sqlWrite = new SqlCommand(preparedCommand, varConnection)) {
            sqlWrite.Prepare();
            sqlWrite.Parameters.AddWithValue("@varData", varData);
            sqlWrite.Parameters.AddWithValue("@varDataNazwa", varDataNazwa);
            try {
                sqlWrite.ExecuteNonQuery();
            } catch (SqlException sqlEx) {
                if (sqlEx.Message.Contains("Violation of PRIMARY KEY constraint")) {
                    MessageBox.Show("Dodanie podanego święta jest niemożliwe. Podane święto istnieje już w bazie danych!", "Bład", MessageBoxButtons.OK, MessageBoxIcon.Error);
                } else {
                    MessageBox.Show(sqlEx.ToString(), "Bład SQL", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            } catch (Exception ex) {
                MessageBox.Show(ex.ToString(), "Bład", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

所以我并没有特别要求办法。我知道怎么做,我可以使用DateTime直接传递给db。只是我想知道为什么它会在一台机器上表现不同。

3 个答案:

答案 0 :(得分:5)

  

日始终按月切换

这听起来很可疑,就像你的同事在他的XP机器上使用英国语言​​环境一样,因为那是在那里约会的常用方法。

但我更关心这个:

  在将其输入DB之前

如果您将其放入数据库,为什么要拨打.ToShortDateString()?这对我来说就像动态sql一样,这意味着一个sql注入漏洞。而不是像这样的东西:

string sql = "INSERT INTO [MyTable] (MyDateColumn) VALUES (" + MyDateVar.ToShortDateString() + ")";
//sql command/connection code omitted from this sample

你需要做这样的事情:

string sql = "INSERT INTO [MyTable] (MyDateColumn) VALUES (@MyDate)"
using (var cn = new SqlConnection("..connection string.."))
using (var cmd = new SqlCommand(sql, cn))
{
    cmd.Parameters.Add("@MyDate", SqlDbType.DateTime).Value = MydateVar;

//remain code omitted

请注意,后一个示例从不将datetime变量转换为字符串。无论用户设置了哪种语言环境,它都可以正常工作。

答案 1 :(得分:1)

我原本以为使用Invariant Culture将日期/时间等内容存储在数据库中会更好。当你从数据库中取出它以向用户显示它时你应该关注区域设置。

您应该使用DateTime.ToString(System.Globalization.CultureInfo.InvariantCulture)

,而不是在数据库中存储ShortDateString

要查看(在代码中)您正在使用的文化,请使用System.Globalization.CultureInfo.CurrentCulture.Name

答案 2 :(得分:0)

听起来非常像区域设置。我会检查运行应用程序的帐户的区域设置,看看是否提供了解释。

至于处理问题,ToBinary上的DateTime方法提供了一种安全的方式来导出值,以便以后可以重新创建它。更好的是,考虑到这将进入数据库,将其传递给SQLCommand,正如其他人所建议的那样。