Pues eso… que esto de las fechas en las consultas es como el cuento de nunca acabar… al menos para mí, jeje.
Lo que me ha pasado esta vez es que he estado usando fechas en una consulta y, como ya comenté hace años, la mejor forma de pasarlas a la consulta de SQL es usando parámetros, hasta aquí todo bien.
' Crear un nuevo objeto del tipo DataAdapter
da = NewSqlDataAdapter(sel, sCon)
da.SelectCommand.Parameters.AddWithValue("@fecha1", fecha1)
da.SelectCommand.Parameters.AddWithValue("@fecha2", fecha2)
En esta ocasión, las fechas las he pasado como argumento a un método normal con el tipo de datos de las fechas (DateTime o Date en VB). Aclaro esto porque cuando se convierte un objeto del tipo fecha a una cadena (que es lo que supongo que hace el SQL cuando va a trabajar con la fecha) ese objeto del tipo fecha se convierte en una fecha y una hora (ver la figura 1).
Figura 1. Los objetos de tipo Date (DateTime) contienen la fecha y la hora.
En este ejemplo, el valor pasado en el primer argumento tiene la fecha y la hora a las 12 de la madrugada, es decir a las 00:00:00 que es lo que ocurre cuando conviertes una fecha de cadena a tipo DateTime.
Pero si la fecha la obtienes, por ejemplo, de un DateTimePicker o simplemente usando DateTime.Now que obtiene la fecha (y hora) actual. En el caso de que ese valor se obtenga a la hora en que escribo esto, mostrará un valor de fecha 2 de junio de 2016 y la hora 13 (01 PM) y 24 minutos con nosecuantos segundos (ver la figura 2).
Figura 2. Now devuelve la fecha y hora actual completa.
En este caso la propiedad Now del objeto fecha devuelve la fecha y la hora actual, y lo que hace la función esa que muestro en la figura 2 (NowDate) es devolver solo la fecha, sin hora… aunque la hora siempre está, pero si no se indica será 00:00:00 (media noche).
Bueno, espero que te pueda servir de ayuda en casos como el que me pasó a mí, que aún habiendo un dato (de la misma fecha en la que hacía la comprobación) no me lo mostraba porque la hora era (por ejemplo las 9 de la noche) y esa fecha no era igual (o menor) que la que estaba guardada en la base de datos (que era el mismo día, pero a las cero horas), en fin…
Pues eso… que esto seguro que lo tengo mil veces publicado en mi sitio, pero hoy lo he ido a buscar, y no lo he encontrado de forma concreta, así que… aquí está para que "yo" lo encuentre… jejeje
¿Por qué buscaba esto?
El caso es el siguiente: necesitaba saber el ID (u otro campo) de una tabla de una base de datos de SQL Server Express 2014 (el tipo de base de datos es indiferente siempre que tenga el método que te comento) haciendo una consulta, concretamente usando LIKE en la propia cadena de selección o consulta.
La consulta es la siguiente:
String.Format(
"SELECT ID FROM Clientes
WHERE Nombre LIKE '%{0}%'
AND Apellidos LIKE '%{1}%'",
nombre, apellidos)
No indico la forma de asignar esa cadena para que uses VB o C#, en el primer caso tendrías que indicar Dim sel = y en el segundo var sel =
A continuación creamos un objeto del tipo Connection y otro del tipo Command y hacemos una llamada al método ExecuteScalar y el valor que devuelva será (en este caso concreto) el ID que estamos buscando o CERO si no lo ha encontrado.
Simplificando (sin tratamiento de error y esas cosas), si el acceso a la base de datos es de SQL Server (en este ejemplo en una instancia de SQLEXPRESS) y usamos las clases definidas en System.Data.SqlClient, el código sería algo así:
Visual Basic:
PublicSharedFunction BuscarCliente2(nombre AsString, apellidos AsString) AsInteger
Dim elID AsInteger = 0
Dim sel =
String.Format(
"SELECT ID FROM Clientes WHERE Nombre LIKE '%{0}%' AND Apellidos LIKE '%{1}%'",
nombre, apellidos)
Dim sCon = ".\sqlexpress;Initial Catalog=LaBaseDeDatos;Integrated Security=True"
Using con AsNewSqlConnection(sCon)
Dim cmd AsNewSqlCommand(sel, con)
con.Open()
elID = CInt(cmd.ExecuteScalar())
con.Close()
EndUsing
Return elID
EndFunction
C#:
publicstaticint BuscarCliente2(string nombre, string apellidos)
{
int elID = 0;
var sel =
String.Format(
"SELECT ID FROM Clientes WHERE Nombre LIKE '%{0}%' AND Apellidos LIKE '%{1}%'",
nombre, apellidos);
var sCon = @".\sqlexpress;Initial Catalog=LaBaseDeDatos;Integrated Security=True";
using (SqlConnection con = newSqlConnection(sCon))
{
SqlCommand cmd = newSqlCommand(sel, con);
con.Open();
elID = Convert.ToInt32(cmd.ExecuteScalar());
con.Close();
}
return elID;
}
Pues eso… que estaba modificando/probando la aplicación esa que en su día te comenté para acceder a los ficheros de FoxPro (o dBase) con la extensión DBF y resulta que me dio error al conectar a la base de datos, concretamente este:
ERROR [IM002] [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified
Así que… me fui a ver mi artículo (Acceso a ficheros dBase (.dbf) desde Visual Basic .NET y C#) y usé otra cadena de conexión (todo esto después de probar a instalar los drivers de VFP -que por cierto me equivoqué e instalé y los de OLEDB en vez de los de ODBC porque no encontré los drivers de este último… y ¡me lié! po zí… pero bueno, ese es otro tema… jum!). La cuestión es que tuve que desinstalar los drivers de OLEDB ya que la cadena de conexión y el tipo de datos que quería usar eran los de ODBC.
Nota aclaratoria del 23/Abr/2015 11:15 Aparte de agregar un nuevo comentario al párrafo anterior, quiero aclararte que: Busqué los drivers de ODBC (que son los que yo quería utilizar) y por error me bajé los de OLEDB y después de instalarlos y probar “con la conexión ODBC” de que no funcionaba -lógico, no son los adecuados- desinstalé los drivers de OLEDB y usé una cadena de conexión diferente que en mi equipo sí funcionaba (sin los drivers de VFP), pero no en el equipo de mi amigo que aún tenía los drivers de VFP que en su día instaló…
Para tu información la cadena que inicialmente estaba usando (y la que funciona en el equipo de mi colega) es esta:
La cuestión es que la de Visual FoxPro Driver a mi no me iba y la de dBASE driver no le iba a mi colega Manolo (le da el error de la figura 1).
Figura 1. Error del controlador/driver dBASE
Así que… tenía que hacer algo para usar uno en un equipo y otro en el otro… y antes de ponerme a saber el nombre del equipo y demás, me dije… jum! esta vez voy a probar primero lo más simple y después ya veré si me tengo que complicar la vida con otras cosas.
Y lo más simple para mi es: ¡probar si puede conectar con una cadena de conexión y si no puede, entonces probar otra! y…
(Ahora, al escribir esto último me recuerda mis tiempos de programador de Quick BASIC y el uso y "mal uso" de ON ERROR RESUME NEXT o lo que es lo mismo: si se produce un error que continúe girando el mundo… ¡hasta que se pare! jaja… en fin…)
Y eso he hecho y eso es lo que me funciona, mi colega aún no lo habrá probado, pero seguro que a él también le funciona; así que… si funciona… ¡todos contentos! 🙂
(y sobre todo, él puede seguir trabajando, yo no, pero él sí jeje)
Y este es el código que he usado (por ahora en Visual Basic .NET ya que mis proyectos los suelo hacer siempre para Visual Basic -salvo excepciones).
El código de la función LeerBases(path) para Visual Basic .NET
PublicSharedFunction LeerBases(ByVal dirDBF AsDirectoryInfo) AsDataSet
Datos = NewDataSet
Dim sBase AsString = dirDBF.FullName
Dim sConn AsString
Dim ficsDbf() AsFileInfo = dirDBF.GetFiles("*.dbf")
If ficsDbf.Length = 0 ThenReturn Datos
' Utilizar varias conexiones y probar con las siguientes si da error (14/Abr/15)
Dim cadenasConexión() AsString = {"Driver={Microsoft Visual FoxPro Driver};SourceType=DBF;SourceDB=" & sBase & ";",
"Driver={Microsoft dBASE Driver (*.dbf)};DriverID=277;Dbq=" & sBase & ";"}
Dim intentosConexion AsInteger = 0
Dim hayError AsBoolean = False
Dim mensajeError AsString = ""
Do
sConn = cadenasConexión(intentosConexion)
Using dbConn AsNew System.Data.Odbc.OdbcConnection(sConn)
Try
dbConn.Open()
ForEach fi AsFileInfoIn ficsDbf
Dim sSelect AsString = "SELECT * FROM " & fi.Name
Dim da AsNew System.Data.Odbc.OdbcDataAdapter(sSelect, dbConn)
Dim dt AsNewDataTable
da.Fill(dt)
If dt.Rows.Count > 0 Then
Datos.Tables.Add(dt)
EndIf
Next
dbConn.Close()
hayError = False
' Salir del bucle,
' no sea que haya más opciones de conectar y no es plan...
Exit Do
Catch ex AsException
mensajeError = _
"Error al abrir la base de datos" & vbCrLf &
ex.Message & vbCrLf &
"Usando: '" & cadenasConexión(intentosConexion) & "'"
hayError = True
' Este es el mensaje de error que me muestra:
' ERROR [IM002] [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified
EndTry
EndUsing
intentosConexion += 1
LoopWhile intentosConexion < cadenasConexión.Length
If hayError Then
System.Windows.Forms.MessageBox.Show(mensajeError,
"Error al conectar a los datos de DBF",
System.Windows.Forms.MessageBoxButtons.OK,
System.Windows.Forms.MessageBoxIcon.Exclamation)
EndIf
Return Datos
EndFunction
Y esto es todo amigos… 🙂
Espero que te sea de utilidad y que si así lo es, me invites a un té o un refresco… y como va a ser complicado que nos veamos para esa invitación (y no es plan de esperar a que eso ocurra en otra vida), puedes invitarme usando el botón de Donar ese que tengo en mi blog, allí, arriba a la derecha o en mi sitio, sí, ese que está allí arriba, donde dice eso de Donativo para el sitio de elGuille.