【问题标题】:conversion from string to type date is not valid从字符串到类型日期的转换无效
【发布时间】:2015-03-01 15:17:07
【问题描述】:

在这件事上我真的需要你的帮助。我已经搜索了许多关于此的类似主题,但找不到适合我的程序的主题。我会尽量简化我的问题并排除与我无关的其他细节。

我的 vb 程序有一个名为 dtpDate 的日期时间选择器,两个名为 btnRecord_Save 和 btnClear_Date 的按钮。

我的 sql 有一个名为 Voucher 的表和一个名为 Voucher_Date (Datatype = Date) 的表

当我的 dtpdate 有一个日期值时,我没有问题,因为它工作得很好,但是如果我通过按 btnClear_date 清除 dtpdate 上的日期,它会给我一个错误(如上面的标题所述)。我想要的只是如果 dtpDate 为空,它将在我的 sql 中存储“NULL”值(列名 = Voucher_date)。

这是我的代码供您参考,我已经编辑并排除了不必要的信息。

类代码(SQLControl)

Imports System.Data.Sql
Imports System.Data.SqlClient

Public Class SQLControl

 Public SQLCon As New SqlConnection With {.ConnectionString i got this!!!}
 Public SQLDA As SqlDataAdapter
 Public SQLDS As DataSet
 Public Params As New List(Of SqlParameter)
 Public RecordCount As Integer
 Public Exception As String
 Private SQLCmd As SqlCommand
 Public Sub AddToVoucher(Voucher_Date As Date)
    Try
        Dim strInsert As String = "INSERT INTO Voucher (Voucher_Date) " & _
                                  "VALUES (" & _
                                  "'" & Voucher_Date & "') "
        SQLCon.Open()
        SQLCmd = New SqlCommand(strInsert, SQLCon)
        SQLCmd.ExecuteNonQuery()
        SQLCon.Close()
        MsgBox("Successfully Added Into Records!")
    Catch ex As Exception
        MsgBox(ex.Message)
    End Try
 End Sub
End Class


Public Class FormMain

 Dim sql As New SQLControl

 Private Sub dtpDate_ValueChanged(sender As System.Object, e As System.EventArgs) Handles dtpDate.ValueChanged
    dtpDate.CustomFormat = "dd/MM/yyyy"
 End Sub

 Private Sub btnClearDate_Click(sender As System.Object, e As System.EventArgs) Handles btnClearDate.Click
    dtpDate.CustomFormat = "        "
    dtpDate.Format = DateTimePickerFormat.Custom
 End Sub

 Private Sub btnRecord_Save_Click(sender As System.Object, e As System.EventArgs) Handles btnRecord_Save.Click
        sql.AddToVoucher(dtpDate.Text)
 End Sub

End Class

【问题讨论】:

  • 使用 SQL 参数而不是将字符串粘合在一起。如果Voucher_Date 是一个实际的日期类型列,则向它发送一个日期时间类型。不需要“格式化”,因为 DateTime 类型没有格式。如果Voucher_Date 不是 Date 类型,它应该是
  • 错误信息非常清楚:无法将字符串转换为日期。所以你需要在创建sql查询时废弃旧的字符串连接,开始使用parameterized sql queries。
  • ..另外,A DateTimePicker 总是有一个值,所以它们永远不会“空白”。虽然在 CodeProject 中有一个 Nullable DTP
  • 正如这些 cmets 所得出的结论,DTP 始终有一个值,它不能设为 NULL。所以我更喜欢做一些代码 在你的保存按钮单击中工作(如 if 语句)并在命令本身中指定 Null .
  • 也请参考这篇之前的帖子。你可能会找到一些东西。setting a DTP to Null

标签: vb.net string date sqldatatypes


【解决方案1】:

我刚刚做了一些实验,确实DateTimePicker(使用你的代码)

dtpDate.CustomFormat = "        "
dtpDate.Format = DateTimePickerFormat.Custom

仍将保留该值。但它会在Text 属性中包含一串空格。所以这就是你的代码发生的事情:

  • 当你有日期的字符串表示时,它会在参数Voucher_Date As Date中隐式转换为Date

  • 当您拥有" " - 它无法转换为Date,因此会出现错误。

现在,我不会告诉你代码的所有错误。我将指出如何以您的自己的编码方式退出您的情况。不幸的是,你最好走参数化路线,这样更容易。

在你的类中声明自定义格式的常量

Private const _cust_Format AS String = "        "

然后这样做

Private Sub btnClearDate_Click(sender As System.Object, e As System.EventArgs) Handles btnClearDate.Click
    dtpDate.CustomFormat = _cust_Format ' <-- so, you always use same number of spaces
    dtpDate.Format = DateTimePickerFormat.Custom
End Sub

Public Sub AddToVoucher(Voucher_Date As DateTime?)
    Try
        Dim strInsert As String = "INSERT INTO Voucher (Voucher_Date) VALUES (@1)"

        SQLCon.Open()
        SQLCmd = New SqlCommand(strInsert, SQLCon)
        ' New code:
        SQLCmd.Parameters.AddWithValue("@1", If(Voucher_Date Is Nothing, DbNull.Value, Voucher_Date)) 
        ' Interestingly, Sql Client doesn't like to set Nothing/Null to value, it likes DBNull.Value. ODP likes both. hmmm...
        SQLCmd.ExecuteNonQuery()
        SQLCon.Close()
        MsgBox("Successfully Added Into Records!")
    Catch ex As Exception
        MsgBox(ex.Message)
    End Try
End Sub 

Private Sub btnRecord_Save_Click(sender As System.Object, e As System.EventArgs) Handles btnRecord_Save.Click
    ' new code:
    Dim d As DateTime? = Nothing
    If dtpDate.Text <> _cust_Format Then
        d = dtpDate.Value   '<-- notice this
    End If  
    sql.AddToVoucher(d)
End Sub

我尚未对其进行测试,但这应该可以让您的代码暂时正常工作。

【讨论】:

  • 效果非常好。在 btnRecord_Save_Click 下,我只需将 dtpDate.text 更改为 dtpDate.CustomFormat。
  • 根据您的评论,我将如何改进我的编码?你能推荐任何网站或教程来构建正确和体面的代码吗?我是一个新手程序员(比如 2 个月),我只是在 youtube 上学习和观看教程。无论如何,我非常感谢您花时间解决我的问题。谢谢 T.S.
  • @Nadz 只需阅读 Microsoft 指南。小东西 - 命名约定。然后,使用公共类成员 - 阅读封装。将Using 与实现IDisposable 的对象一起使用-在您的情况下是命令和连接。例如,如果您的SQLCmd.ExecuteNonQuery() 失败,您在哪里销毁命令和连接? - 无处。所有 SQL 的参数化 - 杀死 Sql 注入,而且它对数据库引擎的性能也更好。检查设计模式。有很多。你会边走边学。我很高兴它对你有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-03
  • 2011-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-30
  • 2015-02-09
相关资源
最近更新 更多