Преобразование содержимого элемента управления текстовым полем ASP.NET .text в формат даты/времени

Я пытаюсь вставить в базу данных различные подробности о событии. Текстовое поле asp.net использует Расширитель календаря (поэтому появляется небольшой календарь и заполняет текстовое поле правильно отформатированной датой). Поле EventDate в моей базе данных Access имеет тип Date/Time. Мне нужно преобразовать текст/строку в формат даты/времени

Я пробовал это до сих пор:

VB:

Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    Dim oleDbConn As New OleDb.OleDbConnection(ConfigurationManager.ConnectionStrings("BookMeetConnString").ConnectionString)
    Dim SqlString As String = "Insert into Events(EventTitle,EventDescription,EventDate,EventCategory) Values
   (@f1,@f2,@f3,@f4)"
    Dim cmd As OleDbCommand = New OleDbCommand(SqlString, oleDbConn)

    Dim strDate As String = tb_eventdate.Text
    Dim dtfi As New System.Globalization.DateTimeFormatInfo
    dtfi.ShortDatePattern = "dd/MM/yyyy"
    dtfi.DateSeparator = "/"
    Dim objDate As DateTime = Convert.ToDateTime(strDate, dtfi)

    cmd.CommandType = CommandType.Text
    cmd.Parameters.AddWithValue("@f1", tb_eventtitle.Text)
    cmd.Parameters.AddWithValue("@f2", tb_eventdescription.Text)
    cmd.Parameters.AddWithValue("@f3", tb_eventdate.Text)
    cmd.Parameters.AddWithValue("@f4", dd_eventcategory.Text)
    oleDbConn.Open()
    cmd.ExecuteNonQuery()
    System.Threading.Thread.Sleep("2000")
    Response.Redirect("~/calendar.aspx")
End Sub

Вот мой клиентский код только для справки:

 <h1>Add An Event!<ajaxToolkit:ToolkitScriptManager
 ID="ToolkitScriptManager1" 
                   runat="server">
               </ajaxToolkit:ToolkitScriptManager>
            </h1>
            <p>Title of Event:
                <asp:TextBox ID="tb_eventtitle" runat="server"></asp:TextBox>
            </p>
            <p>Event Description:
                <asp:TextBox ID="tb_eventdescription" runat="server"></asp:TextBox>
            </p>
            <p>Event Date:
                <asp:TextBox ID="tb_eventdate" runat="server"></asp:TextBox>
                <ajaxToolkit:CalendarExtender ID="tb_eventdate_CalendarExtender" runat="server" 
                    TargetControlID="tb_eventdate">
                </ajaxToolkit:CalendarExtender>
            </p>
            <p>Event Category:
                <asp:DropDownList ID="dd_eventcategory" runat="server" 
                    DataSourceID="SqlDataSource1" DataTextField="CategoryTitle" 
                    DataValueField="CategoryTitle">
                </asp:DropDownList>
            </p>
            <p>
                <asp:Button ID="Button1" runat="server" Text="Submit" />
            </p>

Когда я пытаюсь заполнить форму, я получаю эту ошибку:

ошибка даты и времени

Два моих вопроса:

  1. Что не так с приведенным выше кодом и как успешно использовать класс DateTimeFormatInfo для преобразования строки в дату/время?
  2. Кстати, Calendar Extender вводит дату в текстовое поле в формате американского времени (ММ/ДД/ГГГГ), как мне изменить это на британский формат (ДД/ММ/ГГГГ) (я не мог видеть очевидное свойство в диалоге свойств сделать это?)

Заранее спасибо за ваши ответы!

Адам

РЕДАКТИРОВАТЬ: обновленный код ниже:

Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

    Dim oleDbConn As New OleDb.OleDbConnection(ConfigurationManager.ConnectionStrings("BookMeetConnString").ConnectionString)
    Dim SqlString As String = "Insert into Events(EventTitle,EventDescription,EventDate,EventCategory) Values
 (@f1,@f2,@f3,@f4)"
    Dim cmd As OleDbCommand = New OleDbCommand(SqlString, oleDbConn)
    cmd.CommandType = CommandType.Text
    cmd.Parameters.AddWithValue("@f1", tb_eventtitle.Text)
    cmd.Parameters.AddWithValue("@f2", tb_eventdescription.Text)
    cmd.Parameters.AddWithValue("@f3", DateTime.ParseExact(tb_eventdate.Text, "dd/MM/yyyy",
   CultureInfo.InvariantCulture))
    cmd.Parameters.AddWithValue("@f4", dd_eventcategory.Text)
    oleDbConn.Open()
    cmd.ExecuteNonQuery()
    System.Threading.Thread.Sleep("2000")
    Response.Redirect("~/calendar.aspx")
End Sub

person adaam    schedule 06.04.2013    source источник


Ответы (2)


Я бы порекомендовал вам использовать статический метод DateTime.ParseExact, особенно эту перегрузку:

DateTime.ParseExact(textBox.Text, "dd/MM/yyyy",CultureInfo.InvariantCulture)

Это будет анализировать текст, который у вас есть, по указанному вами конкретному формату ("dd/MM/yyyy" в настоящее время регистр важен, поскольку mm – это минуты, а MM – месяцы). Использование CultureInfo.InvariantCulture гарантирует, что разделители даты будут извлечены из строки формата (второй параметр). Я заметил, что если используется текущая культура, она переопределяет некоторые аспекты строки формата, которую вы передаете ParseExact.


Заметка о CultureInfo

Инвариантная культура хороша еще и потому, что в вашей локальной среде разработки может быть другая региональная настройка информации, чем в среде развертывания. Обычно .NET использует текущий язык и региональные параметры во всех вызовах .ToString и неявном форматировании или синтаксическом анализе. При явной принудительной инвариантности формата и культуры вы менее подвержены проблемам, которые вы не можете воспроизвести локально, но которые существуют в рабочем приложении.


Примечание о форматах даты/времени

При точном анализе формат даты и времени должен строго соответствовать формату ввода. Затем следует принять во внимание следующие примеры:

  • dd соответствует только дням из двух цифр. Таким образом, "dd/MM/yyyy" будет соответствовать "01/01/2013", но не "1/1/2013", потому что он ожидает точное количество цифр для дня. Если вы не хотите использовать ведущие нули, используйте вместо них: d/M/yyyy. Одна буква означает одну цифру для дней менее 10 и две цифры для остальных дней.
  • MM соответствует двузначному месяцу, поэтому все, что применяется к dd и d, одинаково для месяцев.
  • yyyy предполагает, что год будет состоять из 4 цифр. Если вы используете двузначный год, используйте вместо него yy.

Примечание о некоторых провайдерах ADO.NET

Как оказалось в случае с MS Access, правильно проанализированного объекта даты и времени недостаточно для того, чтобы запрос работал. В настоящее время следующий код

 cmd.Parameters.AddWithValue(...)

используется для добавления параметров в запрос. Однако в этом подходе не передается информация поставщику базы данных ADO.NET, которая сообщает, какой тип базы данных использовать для параметра. Я читал на некоторых форумах, что MS Access/OleDb не может разрешить правильный тип во всех случаях. Поэтому я рекомендую следующий подход:

Dim prm as OleDbParameter = _
   New OleDbParameter("@dateTimeParameterName", OleDbType.DateTime)
prm.Value = value  'value is an instance of `System.DateTime` parsed 
                   'from the input
cmd.Parameters.Add(prm)

Приведенный выше код позволяет явно указать тип базы данных параметров, поэтому драйвер OleDb теперь может корректно передавать объект DateTime в базу данных MS Access.

person Ivaylo Slavov    schedule 06.04.2013
comment
Спасибо за это, я обновил свой код, чтобы отразить ваш совет. Однако я все еще получаю сообщение об ошибке, не распознаваемой как допустимая дата и время. Не могли бы вы опубликовать рабочий код, чтобы я мог понять синтаксис/формат метода DateTime.ParseExact? - person adaam; 06.04.2013
comment
@adaam, я пересмотрел свой ответ, чтобы решить некоторые дополнительные проблемы с форматированием, с которыми вы могли столкнуться. Тем не менее я не совсем уверен, что не так с вашим кодом. Можете ли вы сказать мне, когда вы получаете сообщение об ошибке? Вызов DateTime.ParseExact завершается ошибкой или он завершается ошибкой после достижения базы данных? Если второе, возможно, параметр неправильно принят базой данных. - person Ivaylo Slavov; 06.04.2013
comment
Вызов выполнен успешно — значение из текстового поля передано (см. скриншот моего процесса отладки: wherelionsroam. co.uk/valuepassed.PNG). Ошибка несоответствия типа данных в выражении критерия выдается при достижении cmd.ExecuteNonQuery(). - person adaam; 07.04.2013
comment
(P.s. на скриншоте выше я использовал Parse, но я также последовал вашему совету и использовал ParseExact, но все равно получаю ошибки) - person adaam; 07.04.2013
comment
@adaam, похоже, проблема связана с несоответствием типа базы данных. Какой тип данных у вашего столбца? Может быть, сработает указание типа параметра с помощью OleDbType.DateTime/OleDbType.SmallDateTime при передаче параметра в запрос? По крайней мере, именно там, я считаю, возникает проблема, так как синтаксический анализ уже бы удался. Попробуйте выполнить отладку и посмотреть, какой DateTime объект фактически передается - переместите его в локальную переменную вместо вызова ParseExact, в котором вы добавляете параметр. - person Ivaylo Slavov; 07.04.2013
comment
Тип данных в Access — дата/время для столбца EventDate. Как указать тип параметра с помощью OleDbType.Datetime? - person adaam; 07.04.2013
comment
Используйте OleDbParameter prm = new OleDbParameter(parameterName, parameterType); для создания объекта параметра; Используйте prm.Value = value;, где value — проанализированный объект даты, а затем используйте cmd.Parameters.Add(prm); - person Ivaylo Slavov; 07.04.2013
comment
Спасибо, наконец-то я заработал. Я использовал ваш метод выше (определение типа параметра, похоже, помогло!) - person adaam; 08.04.2013

Я использовал следующий короткий код:

//myDateValue is System.DateTime object.
OleDbCommand commandObject = new OleDbCommand(); 
...   
commandObject.Parameters.Add(new OleDbParameter("@ADDED_DATE_PARAM", OleDbType.Date).Value = myDateValue);
person Sedat Kumcu    schedule 09.02.2016