简体   繁体   中英

SQL query works in SSMS but not in VB.net

I have this query which returns a datatable from a view, it works perfect inside SSMS, but when I try to use it within VB.net it returns

The conversion of a nvarchar data type to a datetime, data type resulted in an out-of-range value

在 SSMS 中查看:

SQL in SSMS (Executes without problem):

SELECT [Consecutivo], [Detalle], [MetodoPago], [Fecha], [Concepto], [Monto], [Recuperacion], [Usuario], [UsuarioNombre] FROM [BD_RentaEquipos].[dbo].[Cierres] WHERE datediff(day, [Fecha],'2020/05/12')=0

SQL in VB.NET (Doesn't execute):

Public Function C_Cargar(Optional Fecha As Date? = Nothing) As DataTable
    Dim LeTable As New dsTablas.CierresDataTable
    AbrirConexion()
    'Dim SQL = "SELECT [Consecutivo], [Detalle], [MetodoPago], [Fecha], [Concepto], [Monto], [Recuperacion], [Usuario], [UsuarioNombre] FROM [BD_RentaEquipos].[dbo].[Cierres]" & IIf(Fecha IsNot Nothing, " WHERE datediff(day, [Fecha], '" & New String(Fecha.Value.Year & "/" & Fecha.Value.Month & "/" & Fecha.Value.Day) & "') = 0", "")
    Dim SQL = "SELECT [Consecutivo], [Detalle], [MetodoPago], [Fecha], [Concepto], [Monto], [Recuperacion], [Usuario], [UsuarioNombre] FROM [BD_RentaEquipos].[dbo].[Cierres]" & IIf(Fecha IsNot Nothing, " WHERE datediff(day, [Fecha], ? ) = 0", "")
    cmd = New OdbcCommand(SQL)
    Dim data As OdbcDataReader
    cmd.Connection = CN
    If Fecha IsNot Nothing Then
        With Fecha.Value
            cmd.Parameters.AddWithValue("@Fecha", Fecha)
            'cmd.Parameters.AddWithValue("@Fecha", New String(.Day & "/" & .Month & "/" & .Year))
        End With
    End If
    Try
        data = cmd.ExecuteReader
        While data.Read
            LeTable.Rows.Add()
            With LeTable.Rows(LeTable.Rows.Count - 1)
                .Item("Consecutivo") = data("Consecutivo")
                .Item("Detalle") = data("Detalle").ToString
                .Item("MetodoPago") = data("MetodoPago").ToString
                .Item("Fecha") = data("Fecha")
                .Item("Concepto") = data("Concepto").ToString
                .Item("Monto") = data("Monto")
                .Item("Recuperacion") = data("Recuperacion")
                .Item("Usuario") = data("Usuario")
                .Item("UsuarioNombre") = data("UsuarioNombre")
            End With
        End While
    Catch sqlerror As SqlException
        MsgBox(sqlerror.Message & Chr(13) & sqlerror.Procedure, MsgBoxStyle.Critical, "Excecion de Base de datos #" & sqlerror.Number)
        Err.Clear()
    Catch ex As Exception
        MsgBox(ex.Message, MsgBoxStyle.Critical, "Excecion de Base de datos #" & "0x" & Hex(ex.HResult))
        Err.Clear()
    Finally
        CerrarConexion()
    End Try
    Return LeTable
End Function

I tried different ways without results

Two things, never use IIF if you can help it, secondly dates as string should be in ISO format (yyyy-MM-did)

Dim SQL = $"SELECT [Consecutivo], [Detalle], [MetodoPago], 
                   [Fecha], [Concepto], [Monto], [Recuperacion], 
                   [Usuario], [UsuarioNombre] 
            FROM [BD_RentaEquipos].[dbo].[Cierres]
            " 


cmd = New OdbcCommand()
Dim data As OdbcDataReader
cmd.Connection = CN
If Fecha IsNot Nothing Then
    SQL +=  " WHERE cast([Fecha] as date) = '?' ")
    cmd.Parameters.AddWithValue("@Fecha", Fecha.ToString("yyyy-MM-dd"))
End If
cmd.CommandText = SQL

Also, this is one of the situations where you don't actually need a parameter, you are dealing with a date and can format it and include it as part of the sql text directly, although I didn't.

Since you mentioned SSMS I thought you were probably using SQL Server. To use the Sql provider

Imports System.Data.SqlClient

It is good to keep your database objects local to the method where they are used so you can be sure they are closed and disposed. (they may be using unmanaged resources which are released in their .Dispose method) The Using...End Using blocks assure this even if there is an error. Both the connection and command are in a single Using block in this sample code. Note the comma at the end of the first line of the Using .

You can pass your connection string directly to the constructor of the connection.

When you use parameters with the .Add method you designate the SqlDbType so the server knows what to expect. You are passing in a .net Date type so there is not need to format any strings. ADO will figure it out for you.

If you need to use ODBC for some reason the just replace Sql types with Odbc.

The returned DataTable can be used directly as a .DataSource for a DataGridView in WinForms.

    Public Function C_Cargar(Optional Fecha As Date? = Nothing) As DataTable
    Dim LeTable As New DataTable
    Dim SQL = "SELECT [Consecutivo], [Detalle], [MetodoPago], [Fecha], [Concepto], [Monto], [Recuperacion], [Usuario], [UsuarioNombre] FROM [BD_RentaEquipos].[dbo].[Cierres]"
    Using cn As New SqlConnection("Your connection string"),
            cmd As New SqlCommand()
        If Fecha IsNot Nothing Then
            SQL &= " WHERE datediff(day, [Fecha], @Fecha)=0;"
            cmd.Parameters.Add("@Fecha", SqlDbType.DateTime).Value = Fecha
        End If
        cmd.CommandText = SQL
        cmd.Connection = cn
        cn.Open()
        LeTable.Load(cmd.ExecuteReader)
    End Using
    Return LeTable
End Function

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM