none
Duda de novato

    Pregunta

  • Estimados, hace ya varios dias que vengo trancado con un buscador para mi proyecto.

    Les comento como se compone mi proyecto.

    Tengo una clase de conexión:

    Imports System.Data.SqlClient
    
    Public Class conexion
        Protected cnn As New SqlConnection
    
        Protected Function conectado()
            Try
                cnn = New SqlConnection("Data Source=10.10.10.10;Initial Catalog=midb; User ID=usuario; Password=contraseña")
                cnn.Open()
                Return True
            Catch ex As Exception
                MessageBox.Show("Imposible conectarme al servidor en este momento.", "Conexión con Servidor", MessageBoxButtons.OK, MessageBoxIcon.Error)
                Return False
            End Try
        End Function
    
        Protected Function desconectado()
            Try
                If cnn.State = ConnectionState.Open Then
                    cnn.Close()
                    Return True
                Else
                    Return False
                End If
            Catch ex As Exception
                msgbox(ex.message)
                Return False
            End Try
        End Function
    End Class


    una clase con datos

    Public class vclase
      Dim id as integer
      Dim fecha as date
      Dim nombre as string
    
        Public Property gid
            Get
                Return id
            End Get
            Set(value)
                id = value
            End Set
        End Property
    
        Public Property gfecha
            Get
                Return fecha
            End Get
            Set(value)
                fecha = value
            End Set
        End Property
    
        Public Property gnombre
            Get
                Return nombre
            End Get
            Set(value)
                nombre = value
            End Set
        End Property
    
    Public sub new()
    
    End sub
    
    Public sub new(byval id as integer,byval fecha as date,byval nombre as string)
        gid=id
        gfecha=fecha
        gnombre=nombre
    End sub


    Una clase con las funciones que uso

    Imports System.Data.SqlClient
    
    Public Class fclase
        Inherits conexion
        Dim cmd As New SqlCommand
    
        Public Function mostrar() As DataTable
            Try
                conectado()
                cmd = New SqlCommand("mostrar")
                cmd.CommandType = CommandType.StoredProcedure
                cmd.Connection = cnn
    
                If cmd.ExecuteNonQuery Then
                    Dim dt As New DataTable
                    Dim da As New SqlDataAdapter(cmd)
                    da.Fill(dt)
                    Return dt
                Else
                    Return Nothing
                End If
            Catch ex As Exception
                MsgBox(ex.Message)
                Return Nothing
            Finally
                desconectado()
            End Try
        End Function
    
    Public Function insertar(ByVal dts As vclase) As Boolean
            Try
                conectado()
                cmd = New SqlCommand("crear")
                cmd.CommandType = CommandType.StoredProcedure
                cmd.Connection = cnn
    
                cmd.Parameters.AddWithValue("@fecha", dts.gfecha)
                cmd.Parameters.AddWithValue("@nombre", dts.gnombre)
    
                If cmd.ExecuteNonQuery Then
                    Return True
                Else
                    Return False
                End If
            Catch ex As Exception
                MsgBox(ex.Message)
                Return False
            Finally
                desconectado()
            End Try
        End Function
    
    
    
    ETC...


    Y en la gráfica(form), cuando quiero, por ejemplo, cargar un dato en una tabla sql, solo realizo:

    try
    dim dts as new vclase
    dim func as new fclase
    
    dst.gfecha=dtfecha.text
    dts.gnombre=txtnombre.text
    
    if func.crear(dts) then
    msgbox("registro creado")
    
    etc

    Ahora viene la cuestión, me William me pasó un código en C para crear un buscador en base a una tabla, lo que pude entender del código en c fué:

    Private Sub Form1_Load(sender As Object, e As EventArgs)
    	Dim ConString As String = ConfigurationManager.ConnectionStrings("ConString").ConnectionString
    	Using con As New SqlConnection(ConString)
    		Dim cmd As New SqlCommand("SELECT FirstName FROM Employees", con)
    		con.Open()
    		Dim reader As SqlDataReader = cmd.ExecuteReader()
    		Dim MyCollection As New AutoCompleteStringCollection()
    		While reader.Read()
    			MyCollection.Add(reader.GetString(0))
    		End While
    		txtFirstName.AutoCompleteCustomSource = MyCollection
    		con.Close()
    	End Using
    End Sub

    Eso es lo que interpreté sería en vb.net. El tema es que no logro entender como puedo hacer para que funcione con mi código, ya que ese, se conecta directamente desde el form, tira la consulta, lee, crea el mycollection y luego lo mete en el txtfirstname.....

    Entiendo el código, no como modificarlo para poder usarlo.

    No se si ponerlo en mi clase de funciones, directamente en el form, no se...

    Agradezco si me pudieran orientar en base a lo que expuse.

    Muchas gracias.


    miércoles, 1 de marzo de 2017 4:28

Respuestas

  • dynamicuy,

    Algunas consideraciones:

    - Captura las excepciones en la capa de presentación y no en las capas subyacentes.

    - No es correcto que uses clases del espacio de nombres Windows.Form en los métodos de la capa de acceso a datos, por ejemplo la clase MessageBox, de hecho al quitar el controlador de errores Try Catch (en base a la sugerencia anterior) deja sin sentido el cuadro de mensaje al usuario.

    - Las propiedades de la clase 'vclase' (vaya nombre para descriptivo) no componen de lógica para alguno de los descriptores de acceso (get, set), por tanto basta con escribir Propiedades implementadas automáticamente.

    - Utiliza identificadores descriptivos.

    - etc. 

    Al caso, puedes utilizar la función 'mostrar()' para recuperar un objeto de tipo DataTable (que es el tipo que retorna tu función) para luego convertirlo a una colección que acepte la propiedad 'AutoCompleteCustomSource', por ejemplo:

    Try
    	txtFirstName.AutoCompleteMode = AutoCompleteMode.Suggest
    	txtFirstName.AutoCompleteSource = AutoCompleteSource.CustomSource
    
    	Dim origen = New AutoCompleteStringCollection()
    
    	origen.AddRange(Mostrar().Rows.Cast(Of DataRow).
    		Select(Function(c) c.Field(Of String)("FirstName")).ToArray())
    
    	txtFirstName.AutoCompleteCustomSource = origen
    Catch ex As Exception
    	MessageBox.Show(ex.Message)
    End Try

    No olvides indicar el espacio de nombres: Imports System Linq


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.

    • Marcado como respuesta dynamicuy miércoles, 1 de marzo de 2017 7:05
    miércoles, 1 de marzo de 2017 6:11
  • dynamicuy,

    Te recomiendo concatenar el valor de ambas columnas en la consulta de selección:

    SELECT CONCAT(FirstName, ' ', LastName) AS FullName FROM Employees

    Lo siguiente será seleccionar la expresión que hemos nombrado como FullName

    origen.AddRange(Mostrar().Rows.Cast(Of DataRow).
    		Select(Function(c) c.Field(Of String)("FullName")).ToArray())



    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    • Marcado como respuesta dynamicuy jueves, 2 de marzo de 2017 13:02
    miércoles, 1 de marzo de 2017 16:21
  • Gracias Willams!

    Cuando intenté concatenar el procedimiento me di cuenta de que estaba trabajando con sql 2008 r2 y me tiraba error el concat, la mejor forma de concatenar en ese esenario fué de la siguiente manera:

    SELECT {fn CONCAT(nombre1, {fn CONCAT(' ' , apellido1)}) } as nombre_completo from clientes

    Quería dejar eso ya que le podría servir a alguien!

    Saludos y gracias!

    jueves, 2 de marzo de 2017 13:02

Todas las respuestas

  • dynamicuy,

    Algunas consideraciones:

    - Captura las excepciones en la capa de presentación y no en las capas subyacentes.

    - No es correcto que uses clases del espacio de nombres Windows.Form en los métodos de la capa de acceso a datos, por ejemplo la clase MessageBox, de hecho al quitar el controlador de errores Try Catch (en base a la sugerencia anterior) deja sin sentido el cuadro de mensaje al usuario.

    - Las propiedades de la clase 'vclase' (vaya nombre para descriptivo) no componen de lógica para alguno de los descriptores de acceso (get, set), por tanto basta con escribir Propiedades implementadas automáticamente.

    - Utiliza identificadores descriptivos.

    - etc. 

    Al caso, puedes utilizar la función 'mostrar()' para recuperar un objeto de tipo DataTable (que es el tipo que retorna tu función) para luego convertirlo a una colección que acepte la propiedad 'AutoCompleteCustomSource', por ejemplo:

    Try
    	txtFirstName.AutoCompleteMode = AutoCompleteMode.Suggest
    	txtFirstName.AutoCompleteSource = AutoCompleteSource.CustomSource
    
    	Dim origen = New AutoCompleteStringCollection()
    
    	origen.AddRange(Mostrar().Rows.Cast(Of DataRow).
    		Select(Function(c) c.Field(Of String)("FirstName")).ToArray())
    
    	txtFirstName.AutoCompleteCustomSource = origen
    Catch ex As Exception
    	MessageBox.Show(ex.Message)
    End Try

    No olvides indicar el espacio de nombres: Imports System Linq


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.

    • Marcado como respuesta dynamicuy miércoles, 1 de marzo de 2017 7:05
    miércoles, 1 de marzo de 2017 6:11
  • Muchas gracias Willams! segui tus puntas y me sirvió al pelo, ahora y ya para terminar, como puedo mandarle otro dato?

    ejemplo: "FirstName" & "LastName"  ¿?

    Le doy vueltas y no consigo.

    miércoles, 1 de marzo de 2017 7:42
  • dynamicuy,

    Te recomiendo concatenar el valor de ambas columnas en la consulta de selección:

    SELECT CONCAT(FirstName, ' ', LastName) AS FullName FROM Employees

    Lo siguiente será seleccionar la expresión que hemos nombrado como FullName

    origen.AddRange(Mostrar().Rows.Cast(Of DataRow).
    		Select(Function(c) c.Field(Of String)("FullName")).ToArray())



    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    • Marcado como respuesta dynamicuy jueves, 2 de marzo de 2017 13:02
    miércoles, 1 de marzo de 2017 16:21
  • Gracias Willams!

    Cuando intenté concatenar el procedimiento me di cuenta de que estaba trabajando con sql 2008 r2 y me tiraba error el concat, la mejor forma de concatenar en ese esenario fué de la siguiente manera:

    SELECT {fn CONCAT(nombre1, {fn CONCAT(' ' , apellido1)}) } as nombre_completo from clientes

    Quería dejar eso ya que le podría servir a alguien!

    Saludos y gracias!

    jueves, 2 de marzo de 2017 13:02
  • dynamicuy,

    La consulta sql que muestras contiene sintaxis XQuery (lenguaje para consultas contra un tipo xml), no veo necesario su uso.

    El operador de concatenación en SQL Server es el símbolo de suma '+', de hecho la función CONCAT() se traduce bajo el mismo operador, por lo que la consulta sql quedaría de la siguiente forma:

    SELECT nombre1 + ' ' + apellido1 AS nombre_completo FROM clientes;


    Sin embargo, si la columna [apellido1] tiene marcado la restricción de NULL e intentas concatenar un valor de la columna [nombre1] + NULL obtendrás como resultado NULL a menos que tengas configurado la directiva CONCAT_NULL_YIELDS_NULL (permite configurar el resultado de concatenar NULL con una cadena) en OFF, tarea que no se recomienda porque en futuras versiones de SQL Server el cambio podría producir error.

    ¿Entonces que hacer?, es simple, debes utilizar una función que permita reemplazar NULL en una cadena de longitud cero, por ejemplo la función ISNULL()

    SELECT nombre1 + ISNULL(' ' + apellido1, '') AS nombre_completo FROM clientes;

    La función CONCAT() nos abstrae del problema de NULL, por eso propuse su uso, pero si la versión de SQL Server que ocupas no lo reconoce entonces vale hacer la validación según lo explicado.


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.

    viernes, 3 de marzo de 2017 15:52