Региональные проблемы с C # и базой данных SQL - PullRequest
0 голосов
/ 10 марта 2010

Почему бы dateTimePicker.Value.Date.ToShortDateString(); действовать по-разному в Windows 7 x64 PL, Windows Vista x32 PL и Windows XP PL, насколько мне известно, с точными региональными настройками. Я нашел это трудным способом, которым я делал это преобразование прежде, чем ввести это в DB.

Это работало нормально на Windows 7 (моя машина для разработки), коллега по системе VISTA, но не работало на Windows XP (день менялся на месяц все время). Также в более высоких системах у нас 2010-01-13 отображается на ListView, в то время как в его системе он имеет 13-01-2010.

Я предполагаю, что в моем старом коде у меня может быть больше таких преобразований типов, и мне нужно будет пройти и проверить его, но я хотел бы знать, почему он ведет себя таким же образом в тех же региональных настройках. Я полагаю, что никогда не должен делать такие преобразования, но я научился этому нелегко после долгого времени, когда он работал нормально.

EDIT:

Я использовал его таким образом (закомментировал код, который вызывал проблемы). В старые времена я думал, что ToShortDateString - это единственный способ убедиться, что он помещен в БД без времени (так как я читал DateTimePicker). Теперь я знаю, что должен был использовать .Date для этого DateTimePicker, но теперь я стал умнее, потому что он взорвал меня. Вот код:

    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 непосредственно в БД. Просто я хотел бы знать, почему он ведет себя по-разному на 1 машине.

Ответы [ 3 ]

5 голосов
/ 10 марта 2010

день все время менялся на месяц

Звучит подозрительно, будто ваш коллега использует локализацию в Великобритании на своем компьютере с XP, поскольку это обычный метод для свидания.

Но меня больше волнует это:

до ввода его в БД.

Если вы помещаете это в БД, почему вы звоните .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 голос
/ 10 марта 2010

Я бы подумал, что было бы лучше хранить такие вещи, как дата / время, в базе данных, используя инвариантную культуру. Когда вы выводите его из базы данных, чтобы отобразить его пользователю, вас должны беспокоить региональные настройки.

Вместо того, чтобы хранить ShortDateString в базе данных, вы должны использовать DateTime.ToString(System.Globalization.CultureInfo.InvariantCulture).

Чтобы увидеть (в коде), какую культуру вы используете, просто используйте System.Globalization.CultureInfo.CurrentCulture.Name.

0 голосов
/ 10 марта 2010

Звучит очень похоже на региональные настройки. Я бы проверил региональные настройки учетных записей, с которыми работают приложения, чтобы выяснить, предлагает ли это объяснение.

Что касается решения проблемы, то метод ToBinary в DateTime предлагает безопасный способ экспорта значения таким образом, чтобы его можно было впоследствии восстановить. Еще лучше, учитывая, что это входит в базу данных, - передать значение в SQLCommand, как предлагали другие.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...