none
¿Como evito almacenar datos repetidos en Vb.Net

    Question

  • Saludos a todos, estoy desarrollando una aplicacion muy sencilla en la cual al almacenar un dato (ID) en SQL y esta se encuentre duplicada, me alerte con un mensaje.. MessageBox.Show("el DNI ya ha sido previamente guardado", "Error").

    Este es el codigo que estoy ocupando, agradecere a todos su apoyo en este sentido.

     

    ----

    Public Class Prueba

        Private Sub Prueba_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            'TODO: esta línea de código carga datos en la tabla 'DatosDS.datos' Puede moverla o quitarla según sea necesario.
            Me.DatosTableAdapter.Fill(Me.DatosDS.datos)

        End Sub

     

        Private Sub DatosBindingNavigatorSaveItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DatosBindingNavigatorSaveItem.Click

            Me.Validate()
            Me.DatosBindingSource.EndEdit()
            Me.TableAdapterManager.UpdateAll(Me.DatosDS)

        End Sub

     

     Private Sub btnGuardar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGuardar.Click

            Me.Validate()
            Me.DatosBindingSource.EndEdit()
            Me.TableAdapterManager.UpdateAll(Me.DatosDS)

        End Sub

        Private Sub btnLimpiar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLimpiar.Click

            DNITextBox.Clear()
            NombreTextBox.Clear()
            ApellidosTextBox.Clear()

        End Sub

        Private Sub btnSalir_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSalir.Click

            Me.Close()

        End Sub

        Private Sub DNITextBox_Validating(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles DNITextBox.Validating

            'If Me.DatosBindingSource = "         " Then
            '    MessageBox.Show("el DNI ya ha sido previamente guardado", "Error")
            '    DNITextBox.Clear()

            'End If
        End Sub
    End Class

     

    Friday, August 13, 2010 9:01 AM

Answers

  • "alcazar1976" escribió:

    > estoy desarrollando una aplicacion muy sencilla en la cual al almacenar
    > un dato (ID) en SQL y esta se encuentre duplicada, me alerte con un
    > mensaje.. MessageBox.Show("el DNI ya ha sido previamente guardado", "Error").

    Hola:

    Si en la tabla de tu base de datos de SQL Server, tienes establecida su correspondiente CLAVE PRINCIPAL, al haber configurado un origen de datos en tu aplicación de Visual Basic, digo yo que dicho origen de datos ha tenido que reconocer correctamente el campo que compone la clave principal de la tabla.

    Si es así, mientras que tú añades registros, o modificas los existentes, desde el propio formulario, obtendrás una excepción si el valor del campo ID ya existe en el objeto DataTable llamado «datos».

    Ahora bien, para no recibir esos mensajes de error, tienes que desactivar las restricciones de clave única existentes en la clave principal del objeto DataTable, y controlar tú los propios mensajes de error.

    A nivel del formulario declara los siguientes campos:

        Private m_currentPosition As Integer
        Private m_error As Boolean

    Ahora, en el evento Load del formulario ejecutarías:

        Private Sub Form1_Load( _
            ByVal sender As Object, _
            ByVal e As EventArgs) Handles MyBase.Load

            ' Rellenamos el objeto DataTable subyacente.
            Me.DatosTableAdapter.Fill(Me.DatosDS.datos)

            ' Deshabilitamos las restricciones.
            DatosDS.EnforceConstraints = False

        End Sub

    Y en el evento ListChanged del control BindingSource, capturarías la excepción producida:

        Private Sub DatosBindingSource_ListChanged( _
            ByVal sender As Object, _
            ByVal e As System.ComponentModel.ListChangedEventArgs) _
            Handles DatosBindingSource.ListChanged

            m_currentPosition = DatosBindingSource.Position

            If (m_currentPosition = -1) Then Return

            Try
                ' Habilitamos de nuevo las restricciones para
                ' generar una excepción si existen valores que
                ' infringen la clave principal del objeto DataTable.
                '
                DatosDS.EnforceConstraints = True

            Catch ex As Exception
                If ((e.ListChangedType = System.ComponentModel.ListChangedType.ItemChanged) Or _
                    (e.ListChangedType = System.ComponentModel.ListChangedType.ItemAdded)) Then

                    Dim dt As DataTable = DatosDS.datos

                    ' Referenciamos la fila actual
                    Dim row As DataRow = dt.Rows(e.NewIndex)

                    ' Deshechamos las modificaciones efectuadas en la fila.
                    row.RejectChanges()

                    m_error = True

                   MessageBox.Show("el DNI ya ha sido previamente guardado", "Error")

                End If

            Finally
                ' Deshabilitamos de nuevo las restricciones.
                DatosDS.EnforceConstraints = False

            End Try

        End Sub

    Si te interesa regresar al registro donde se ha producido el error, en el evento PositionChanged del control BindingSource ejecutarías:

        Private Sub DatosBindingSource_PositionChanged( _
            ByVal sender As Object, _
            ByVal e As EventArgs) _
            Handles DatosBindingSource.PositionChanged

            If (m_error) Then
                DatosBindingSource.Position = m_currentPosition
                m_error = False
            End If

        End Sub

    Adapta el ejemplo a tus necesidades.

    Un saludo

     


    Enrique Martínez [MS MVP - VB]
    Saturday, August 14, 2010 8:24 AM
    Moderator
  • "alcazar1976" escribió:

    > lo quise implementar al codigo que pienso entregar para desarrollar
    > el programa de la biblioteca, pero resulta que en esta ocasion,
    > no me respeta el mensaje de codio repetido, e inclusive, lo almacena.

    Si "no te respeta el mensaje de código repetido, e inclusive, te lo almacena" en la base de datos, no me queda más que pensar que la tabla que estás utilizando NO TIENE ESTABLECIDA SU CORRESPONDIENTE CLAVE PRINCIPAL.


    >  Te anexo el codo correspondiente para que me hagas favor de
    > revisarlo y me orientes de nuevo con mis errores.

    Solamente me he entretenido en revisar el código existente en los siguientes procedimientos:

      - Publicaciones_Load_1

      - PUBLICACIONESBindingSource_ListChanged

      - PUBLICACIONESBindingSource_PositionChanged

    y están LO MISMO que en el ejemplo que te indiqué.

    No he revisado los restantes procedimientos porque, aparte de que no tengo tiempo para entretenerme a diseñar el formulario con todos los controles que en él utilizas, incluido el origen de datos, tampoco tengo la base de datos que tú estás usando, y creo que tampoco tiene nada que ver el código que ejecutas en ellos con el tema de los registros duplicados.

    Si la tabla de la base de datos tiene establecida su clave principal, y no admite registros duplicados, entiendo que NO PUEDE PERMITIR ALMACENAR REGISTROS DUPLICADOS, y si tú dices que almacena los registros que les envías, pues no me queda más que pensar que ni la tabla tiene ninguna clave principal, y menos aún, el origen de datos que estás utilizando en el formulario (PUBLICACIONESDS).

    Así que asegúrate bien que tanto la tabla de la base de datos como los objetos DataTable incluidos en el origen de datos de tu proyecto, no permitan registros duplicados. No se me ocurre otra cosa que sea la causa de que se permitan añadir registros duplicados a la tabla de la base de datos.

    NOTA: te advierto que mañana comienzo mis vacaciones anuales, por lo que estaré ausente hasta el próximo día 1 de septiembre, así que si ves que no te respondo, ya sabes el motivo. :-)

     

     

     


    Enrique Martínez [MS MVP - VB]
    • Marked as answer by alcazar1976 Sunday, August 15, 2010 6:40 PM
    Sunday, August 15, 2010 2:36 PM
    Moderator
  • "alcazar1976" escribió:

    > Hay una tabla de esas dos que si permite almacenar datos duplicados, y es la
    > tabla capitulos (no esta habilitado el primary key), en la tabla publicaciones
    > si esta habilitada la llave primaria.

    Entonces será en la tabla Capitulos donde se almacenan datos duplicados, porque no creo que sea en la tabla Publicaciones, ya que ésta última sí dispone de su correspondiente clave principal.


    > La cuestion seria que unicamente me comparase el campo Codigotextbox.text si
    > se encuentra repetido o no.  En caso de encontrarse repetido, que no almacene
    > nada, y de no ser asi, permita el almacenamiento.

    Si te refieres al campo Codigo de la tabla Publicaciones, no tienes que comparar nada, porque si aplicas el código que te indiqué, es imposible que en el objeto DataTable existan registros duplicados, por tanto, cuando envíes dicho objeto DataTable a la base de datos, en ésta tampoco pueden existir registros duplicados, ya que la tabla Publicaciones tiene establecida una clave principal, y su motor de base de datos, va a impedir que existan registros duplicados.

    Para hacer eso, tienes que RELACIONAR las dos tablas por un campo común a ambas, que me imagino sería el campo CODIGO, de tal manera que cada uno de los registros de la tabla Capitulos se relacionase con un único registro de la tabla Publicaciones. Es decir, la tabla Publicaciones puede relacionarse con multitud de registros de la tabla Capitulos (porque una publicación puede tener varios capítulos), pero la tabla Capitulos únicamente se puede relacionar con un registro existente en la tabla Publicaciones (porque los capítulos de un libro sólo pertenecen a un libro o publicación), lo que se suele conocer como una relación de «uno a varios» entre las tablas Publicaciones y Capitulos.

    Y a la tabla Capitulos, también le tienes que establecer una clave principal, procurando que en dicha clave no participe el campo CODIGO con el cual se relaciona con la tabla Publicaciones. En esta tabla podrías crear un nuevo campo Autonumérico o Identity, que sea el que componga la clave principal de la tabla Capitulos.

    > Me.PUBLICACIONESTableAdapter.Update(Me.PUBLICACIONESDS.PUBLICACIONES)
    >
    > Me.CAPITULOSTableAdapter.Update(Me.CAPITULOSDS.CAPITULOS)

    Observo que en tu aplicación estás utilizando DOS ORÍGENES DE DATOS DISTINTOS; un origen de datos para la tabla Publicaciones (PUBLICACIONESDS) y otro distinto para la tabla Capitulos (CAPITULOSDS).

    Si utilizas dos orígenes de datos distintos, ES IMPOSIBLE RELACIONAR LAS DOS TABLAS, al menos en los orígenes de datos existentes en tu aplicación (objetos DataSet), porque que yo sepa, hasta la fecha no se pueden relacionar dos objetos DataTable existentes en diferentes objetos DataSet. Es como si quisieras relacionar dos tablas que existen en diferentes bases de datos.

    Si tanto la tabla Publicaciones como la tabla Capitulos existen en la misma base de datos, es ahí donde tienes que efectuar la relación entre ambas tablas, de tal manera que cuando crees el orígen de datos en tu proyecto, selecciones las dos tablas de la base de datos para que el propio origen de datos detecte la relación existente y la aplique en el origen de datos que deseas crear.

    ¿Que no quieres crear la relación en la propia base de datos? Entonces tendrás que crear la relación manualmente en el origen de datos del proyecto de Visual Basic. Pero para ello, TIENES QUE UTILIZAR EL MISMO ORIGEN DE DATOS que contenga a las dos tablas, porque como te he indicado anteriormente, no se puede relacionar dos objetos DataTable (dos tablas) que existen en diferentes objetos DataSet (en dos bases de datos).

    Cuando tengas creada la relación entre las dos tablas, nunca se podrán duplicar registros en la tabla Publicaciones, porque tanto el objeto DataTable como la propia tabla de la base de datos, tienen establecida una clave principal (el campo CODIGO). Y nunca se permitirá añadir un nuevo registro, o actualizar alguno existente en la tabla Capitulos, que no se relacione con ningún registro existente en la tabla Publicaciones.

    Por supuesto, en la tabla Capitulos se pueden duplicar registros, porque una publicación (un libro) puede tener varios capítulos. Por ejemplo, habrán registros que tengan el mismo CODIGO de la tabla Publicaciones, y eso es normal que así suceda. Pero si le has añadido una clave principal a la tabla Capitulos mediante un campo Autonumérico o Identity, cada uno de los registros de la tabla Capitulos serán únicos, aunque exista el mismo CODIGO en varios registros de la tabla Capitulos.

    El "truco" que te indiqué en mi primer mensaje, funciona bien cuando hablamos de un objeto DataTable existente en el origen de datos (objeto DataSet), y la tabla tiene establecida una clave principal. Pero si no se reúnen los requisitos necesarios, ¿cómo quieres que funcione? ¡En la vida funcionará! :-)

    Me parece a mí que vas a tener que diseñar primeramente la base de datos, para establecer correctamente las relaciones entre sus tablas, y vas a tener que diseñar nuevamente el origen de datos de tu proyecto, para que en UN ÚNICO ORIGEN DE DATOS coexistan ambas tablas: Publicaciones y Capitulos. Y esto ya se sale fuera del asunto por el que iniciastes ésta conversación, por lo que te aconsejaría que iniciaras nuevas conversaciones (preguntas, hilos) para las nuevas dudas o problemas que te surgan. Aparte que voy a estar de vacaciones y no sé si te voy a poder responder.

     


    Enrique Martínez [MS MVP - VB]
    Monday, August 16, 2010 4:58 AM
    Moderator

All replies

  • No entiendo que problema tienes... si en SQL DNI está marcado como "UNIQUE" no te dejará guardar registros duplicados.
    Friday, August 13, 2010 11:31 AM
  • hola

    deberias valiarlo previo a realizar la operacion de insert

    analiza este articulo

    [ADO.NET] Parte 5 - Ejemplos Simples Operaciones CRUD

    veras alli un metodo Exist() el cual valia si esta el registro y luego procede con un insert o update

    descarga el ejemplo de codigo en vb.net y a aliza la tecnia aplicada, es lo mismo que eberias aplicar en tu caso, solo que si detecta que existe lanzas un mensaje avisando

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    Friday, August 13, 2010 12:13 PM
  • Asi es, cuando intento almacenar datos repetidos el programa marca un error de excepcion de SQL, quiero evitar eso alertando al usuario con un textbox y no permitiendo guardar esos cambios.
    Saturday, August 14, 2010 4:06 AM
  • Gracias por tu respuesta Leandro, intente adaptar el codigo que mencionates, pero no pude, sigo con el mismo problema, continuare intentanto....
    Saturday, August 14, 2010 4:07 AM
  • "alcazar1976" escribió:

    > estoy desarrollando una aplicacion muy sencilla en la cual al almacenar
    > un dato (ID) en SQL y esta se encuentre duplicada, me alerte con un
    > mensaje.. MessageBox.Show("el DNI ya ha sido previamente guardado", "Error").

    Hola:

    Si en la tabla de tu base de datos de SQL Server, tienes establecida su correspondiente CLAVE PRINCIPAL, al haber configurado un origen de datos en tu aplicación de Visual Basic, digo yo que dicho origen de datos ha tenido que reconocer correctamente el campo que compone la clave principal de la tabla.

    Si es así, mientras que tú añades registros, o modificas los existentes, desde el propio formulario, obtendrás una excepción si el valor del campo ID ya existe en el objeto DataTable llamado «datos».

    Ahora bien, para no recibir esos mensajes de error, tienes que desactivar las restricciones de clave única existentes en la clave principal del objeto DataTable, y controlar tú los propios mensajes de error.

    A nivel del formulario declara los siguientes campos:

        Private m_currentPosition As Integer
        Private m_error As Boolean

    Ahora, en el evento Load del formulario ejecutarías:

        Private Sub Form1_Load( _
            ByVal sender As Object, _
            ByVal e As EventArgs) Handles MyBase.Load

            ' Rellenamos el objeto DataTable subyacente.
            Me.DatosTableAdapter.Fill(Me.DatosDS.datos)

            ' Deshabilitamos las restricciones.
            DatosDS.EnforceConstraints = False

        End Sub

    Y en el evento ListChanged del control BindingSource, capturarías la excepción producida:

        Private Sub DatosBindingSource_ListChanged( _
            ByVal sender As Object, _
            ByVal e As System.ComponentModel.ListChangedEventArgs) _
            Handles DatosBindingSource.ListChanged

            m_currentPosition = DatosBindingSource.Position

            If (m_currentPosition = -1) Then Return

            Try
                ' Habilitamos de nuevo las restricciones para
                ' generar una excepción si existen valores que
                ' infringen la clave principal del objeto DataTable.
                '
                DatosDS.EnforceConstraints = True

            Catch ex As Exception
                If ((e.ListChangedType = System.ComponentModel.ListChangedType.ItemChanged) Or _
                    (e.ListChangedType = System.ComponentModel.ListChangedType.ItemAdded)) Then

                    Dim dt As DataTable = DatosDS.datos

                    ' Referenciamos la fila actual
                    Dim row As DataRow = dt.Rows(e.NewIndex)

                    ' Deshechamos las modificaciones efectuadas en la fila.
                    row.RejectChanges()

                    m_error = True

                   MessageBox.Show("el DNI ya ha sido previamente guardado", "Error")

                End If

            Finally
                ' Deshabilitamos de nuevo las restricciones.
                DatosDS.EnforceConstraints = False

            End Try

        End Sub

    Si te interesa regresar al registro donde se ha producido el error, en el evento PositionChanged del control BindingSource ejecutarías:

        Private Sub DatosBindingSource_PositionChanged( _
            ByVal sender As Object, _
            ByVal e As EventArgs) _
            Handles DatosBindingSource.PositionChanged

            If (m_error) Then
                DatosBindingSource.Position = m_currentPosition
                m_error = False
            End If

        End Sub

    Adapta el ejemplo a tus necesidades.

    Un saludo

     


    Enrique Martínez [MS MVP - VB]
    Saturday, August 14, 2010 8:24 AM
    Moderator
  • Mil gracias por tu respuesta, Enrique....  Adapte el codigo como me lo recomendaste, sigo tentiendo un problema, ya que al guardar de nuevo datos en el programa me muestra el siguiente error:

     

    No se controló SqlCeExeption

    No se puede insertar un valor duplicado en un índice único. [ Table name = datos,Constraint name = PK_datos ]

     

    Señalandome con el apuntador (flecha amarilla) en la parte del siguiente codigo:

    Me.TableAdapterManager.UpdateAll(Me.DatosDS)

     

    El detalle del error es el siguiente:

    {"No se puede insertar un valor duplicado en un índice único. [ Table name = datos,Constraint name = PK_datos ]"}

     

    Reitero mi agradecimiento por la atencion prestada hacia mi persona, un saludo.

    Saturday, August 14, 2010 8:45 AM
  • Enrique, quizas algo habia mal en mi codigo, pero funciono!!!!  estoy sumamente agradecido con tu atencion, un saludo desde Mexico.
    Saturday, August 14, 2010 8:48 AM
  • > No se controló SqlCeExeption
    >
    > No se puede insertar un valor duplicado en un índice único.
    > [ Table name = datos,Constraint name = PK_datos ]

    Pero ese error se produce cuando llamas al método UpdateAll del objeto TableAdapterManager, y lógicamente, si la tabla no admite registros duplicados, ¡zas! ¡Excepción al canto!

    Lo que yo te he explicado anteriormente es para no permitir registros duplicados en el propio objeto DataTable, de tal manera que, si no existen registros duplicados en éste último objeto, difícilmente vas a poder enviar a la base de datos registros duplicados. :-)

     


    Enrique Martínez [MS MVP - VB]
    Saturday, August 14, 2010 10:05 AM
    Moderator
  • Asi es, tienes razon, afortunadamente ya pude reparar ese error, estoy revisando algunas otras cuestiones que le puedo adecuar, ya que este programa que estoy desarrollando (con tu ayuda y la de otros usuarios mas) pienso obsequiarlo a una biblioteca publica. Muy agradecido contigo, me despido.
    Saturday, August 14, 2010 10:13 AM
  • Saludos de Nuevo SoftJaen...  te escribo de nuevo para tomar prestada un poco de tu atencion, al igual que tu apoyo ya que como en el codigo anterior si obtube una respuesta satisfactoria a mi problema, lo quise implementar al codigo que pienso entregar para desarrollar el programa de la biblioteca, pero resulta que en esta ocasion, no me respeta el mensaje de codio repetido, e inclusive, lo almacena.  Te anexo el codo correspondiente para que me hagas favor de revisarlo y me orientes de nuevo con mis errores. 

     

    Public Class Publicaciones

        Private m_currentPosition As Integer
        Private m_error As Boolean

        Private Sub Publicaciones_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize

            Dim myControl As Control
            myControl = sender

            If myControl.Size.Height <> myControl.Size.Width Then
                myControl.Size = New Size(myControl.Size.Width, myControl.Size.Width)

            End If

        End Sub

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPublicacionesCerrar.Click

            frmMenu.MenuStrip1.Enabled = True
            Me.Close()

        End Sub


        Private Sub btnPublicacionesLimpiar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPublicacionesLimpiar.Click


            CODIGOTextBox.Clear()
            SIGNATURAComboBox.Text = String.Empty
            TITULOTextBox.Clear()
            TIPOComboBox.Text = String.Empty
            AUTORTextBox.Clear()
            EDITORIALTextBox.Clear()
            EDICIONTextBox.Clear()
            PAGSTextBox.Clear()
            ISBNTextBox.Clear()
            IDIOMATextBox.Clear()
            Me.CAPITULOSDS.Clear()


            ErrorProvider1.Clear()

            btnPublicacionesGuardar.Enabled = False


        End Sub


        Private Sub Publicaciones_Load_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
     

            ' Rellenamos el objeto DataTable subyacente.
            Me.PUBLICACIONESTableAdapter.Fill(Me.PUBLICACIONESDS.PUBLICACIONES)

            ' Deshabilitamos las restricciones.
            PUBLICACIONESDS.EnforceConstraints = False



            '***TODO: esta línea de código carga datos en la tabla 'PUBLICACIONESDS.PUBLICACIONES' Puede moverla o quitarla según sea necesario.
            Me.PUBLICACIONESBindingSource.AddNew()
            '***TODO: esta línea de código carga datos en la tabla 'CAPITULOSDS.CAPITULOS' Puede moverla o quitarla según sea necesario.
            Me.CAPITULOSBindingSource.AddNew()
            Me.CAPITULOSDS.Clear()


            Me.WindowState = FormWindowState.Maximized
            Me.CAPITULOSDS.Clear()




        End Sub

        Private Sub btnPublicacionesGuardar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPublicacionesGuardar.Click

            Dim DBconexion As New SqlClient.SqlConnection(My.MySettings.Default.DBConnectionString)
            DBconexion.Open()


            If Me.Validate() Then
                Me.PUBLICACIONESBindingSource.EndEdit()
                Me.PUBLICACIONESTableAdapter.Update(Me.PUBLICACIONESDS.PUBLICACIONES)

                Me.CAPITULOSBindingSource.EndEdit()
                Me.CAPITULOSTableAdapter.Update(Me.CAPITULOSDS.CAPITULOS)
                Me.CAPITULOSDS.Clear()

            Else
                System.Windows.Forms.MessageBox.Show(Me, "Errores al guardar la publicacion")
            End If

            DBconexion.Close()

            CODIGOTextBox.Clear()
            SIGNATURAComboBox.Text = String.Empty
            TITULOTextBox.Clear()
            TIPOComboBox.Text = String.Empty
            AUTORTextBox.Clear()
            EDITORIALTextBox.Clear()
            EDICIONTextBox.Clear()
            PAGSTextBox.Clear()
            ISBNTextBox.Clear()
            IDIOMATextBox.Clear()
            Me.CAPITULOSDS.Clear()


            ErrorProvider1.Clear()


            btnPublicacionesGuardar.Enabled = (Len(CODIGOTextBox.Text) > 0) And (Len(TITULOTextBox.Text) > 0) And (Len(AUTORTextBox.Text) > 0)



        End Sub

        Private Sub CODIGOTextBox_Validating(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles CODIGOTextBox.Validating

            If Me.CODIGOTextBox.Text.Length = 0 Then
                ErrorProvider1.SetError(Me.CODIGOTextBox, "El código Dewey es obligatorio")
            Else
                ErrorProvider1.SetError(Me.CODIGOTextBox, "")
            End If
            btnPublicacionesGuardar.Enabled = (Len(CODIGOTextBox.Text) > 0) And (Len(TITULOTextBox.Text) > 0) And (Len(AUTORTextBox.Text) > 0)

        End Sub

        Private Sub TITULOTextBox_Validating(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles TITULOTextBox.Validating

            If Me.TITULOTextBox.Text.Length = 0 Then
                ErrorProvider1.SetError(Me.TITULOTextBox, "El titulo de la publicación es obligatorio")
            Else
                ErrorProvider1.SetError(Me.TITULOTextBox, "")
            End If
            btnPublicacionesGuardar.Enabled = (Len(CODIGOTextBox.Text) > 0) And (Len(TITULOTextBox.Text) > 0) And (Len(AUTORTextBox.Text) > 0)

        End Sub

        Private Sub AUTORTextBox_Validating(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles AUTORTextBox.Validating

            If Me.AUTORTextBox.Text.Length = 0 Then
                ErrorProvider1.SetError(Me.AUTORTextBox, "El nombre del autor de la publicación es obligatorio")
            Else
                ErrorProvider1.SetError(Me.AUTORTextBox, "")
            End If
            btnPublicacionesGuardar.Enabled = (Len(CODIGOTextBox.Text) > 0) And (Len(TITULOTextBox.Text) > 0) And (Len(AUTORTextBox.Text) > 0)

        End Sub

        Private Sub CAPITULOSDataGridView_EditingControlShowing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) Handles CAPITULOSDataGridView.EditingControlShowing

            If TypeOf e.Control Is TextBox Then
                DirectCast(e.Control, TextBox).CharacterCasing = CharacterCasing.Upper
            End If

        End Sub

        Private Sub CAPITULOSDataGridView_CellLeave(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles CAPITULOSDataGridView.CellLeave

            If e.ColumnIndex = 0 Then 'si el indice de la columna es 0 = significa que estas en la columna del id
                '        'aqui empieza el codigo para establecer el valor en las demas celdas
                Dim ind As Integer = e.RowIndex

                Me.CAPITULOSDataGridView.Item(1, ind).Value = CODIGOTextBox.Text '1 es el indice de la columna.varia segun tu caso
                'Me.DataGridView1.Item(0, ind).Value = TextBox1.Text
            End If

        End Sub

        Private Sub PUBLICACIONESBindingSource_ListChanged(ByVal sender As System.Object, ByVal e As System.ComponentModel.ListChangedEventArgs) Handles PUBLICACIONESBindingSource.ListChanged

            m_currentPosition = PUBLICACIONESBindingSource.Position

            If (m_currentPosition = -1) Then Return

            Try
                ' Habilitamos de nuevo las restricciones para
                ' generar una excepción si existen valores que
                ' infringen la clave principal del objeto DataTable.
                PUBLICACIONESDS.EnforceConstraints = True

            Catch ex As Exception
                If ((e.ListChangedType = System.ComponentModel.ListChangedType.ItemChanged) Or _
                    (e.ListChangedType = System.ComponentModel.ListChangedType.ItemAdded)) Then

                    Dim dt As DataTable = PUBLICACIONESDS.PUBLICACIONES

                    ' Referenciamos la fila actual
                    Dim row As DataRow = dt.Rows(e.NewIndex)

                    ' Deshechamos las modificaciones efectuadas en la fila.
                    row.RejectChanges()
                    m_error = True
                    MessageBox.Show("Ya ha sido guardado previamente el codigo: " & CODIGOTextBox.Text, "Error")
                End If

            Finally
                ' Deshabilitamos de nuevo las restricciones.
                PUBLICACIONESDS.EnforceConstraints = False
            End Try

        End Sub

        Private Sub PUBLICACIONESBindingSource_PositionChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PUBLICACIONESBindingSource.PositionChanged

            If (m_error) Then
                PUBLICACIONESBindingSource.Position = m_currentPosition
                m_error = False
            End If

        End Sub


        Private Sub PUBLICACIONESBindingNavigatorSaveItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PUBLICACIONESBindingNavigatorSaveItem.Click

            Me.Validate()
            Me.PUBLICACIONESBindingSource.EndEdit()
            Me.PUBLICACIONESTableAdapter.Update(Me.PUBLICACIONESDS.PUBLICACIONES)
            Me.PUBLICACIONESDS.Clear()

        End Sub
    End Class

     

    Sin otro particular, quedo pendiente de tu respuesta.   Atentamente: alcazar1976

    Sunday, August 15, 2010 8:08 AM
  • "alcazar1976" escribió:

    > lo quise implementar al codigo que pienso entregar para desarrollar
    > el programa de la biblioteca, pero resulta que en esta ocasion,
    > no me respeta el mensaje de codio repetido, e inclusive, lo almacena.

    Si "no te respeta el mensaje de código repetido, e inclusive, te lo almacena" en la base de datos, no me queda más que pensar que la tabla que estás utilizando NO TIENE ESTABLECIDA SU CORRESPONDIENTE CLAVE PRINCIPAL.


    >  Te anexo el codo correspondiente para que me hagas favor de
    > revisarlo y me orientes de nuevo con mis errores.

    Solamente me he entretenido en revisar el código existente en los siguientes procedimientos:

      - Publicaciones_Load_1

      - PUBLICACIONESBindingSource_ListChanged

      - PUBLICACIONESBindingSource_PositionChanged

    y están LO MISMO que en el ejemplo que te indiqué.

    No he revisado los restantes procedimientos porque, aparte de que no tengo tiempo para entretenerme a diseñar el formulario con todos los controles que en él utilizas, incluido el origen de datos, tampoco tengo la base de datos que tú estás usando, y creo que tampoco tiene nada que ver el código que ejecutas en ellos con el tema de los registros duplicados.

    Si la tabla de la base de datos tiene establecida su clave principal, y no admite registros duplicados, entiendo que NO PUEDE PERMITIR ALMACENAR REGISTROS DUPLICADOS, y si tú dices que almacena los registros que les envías, pues no me queda más que pensar que ni la tabla tiene ninguna clave principal, y menos aún, el origen de datos que estás utilizando en el formulario (PUBLICACIONESDS).

    Así que asegúrate bien que tanto la tabla de la base de datos como los objetos DataTable incluidos en el origen de datos de tu proyecto, no permitan registros duplicados. No se me ocurre otra cosa que sea la causa de que se permitan añadir registros duplicados a la tabla de la base de datos.

    NOTA: te advierto que mañana comienzo mis vacaciones anuales, por lo que estaré ausente hasta el próximo día 1 de septiembre, así que si ves que no te respondo, ya sabes el motivo. :-)

     

     

     


    Enrique Martínez [MS MVP - VB]
    • Marked as answer by alcazar1976 Sunday, August 15, 2010 6:40 PM
    Sunday, August 15, 2010 2:36 PM
    Moderator
  • Saludos de Nuevo Enrique.   Hay una tabla de esas dos que si permite almacenar datos duplicados, y es la tabla capitulos (no esta habilitado el primary key), en la tabla publicaciones si esta habilitada la llave primaria. Esto es, por que tengo otra opcion de busqueda de capitulos, y ahi aparece el codigo del libro en donde lo encuentre.  La cuestion seria que unicamente me comparase el campo Codigotextbox.text si se encuentra repetido o no.  En caso de encontrarse repetido, que no almacene nada, y de no ser asi, permita el almacenamiento.

    Esa es en realidad la cuestion, buieno en caso de no encontrarte espero que sean lo meojr para ti las vacaciones, un saludo y como siempre, reitero mi agradecimiento hacia tu persona.

     

    Sunday, August 15, 2010 6:40 PM
  • "alcazar1976" escribió:

    > Hay una tabla de esas dos que si permite almacenar datos duplicados, y es la
    > tabla capitulos (no esta habilitado el primary key), en la tabla publicaciones
    > si esta habilitada la llave primaria.

    Entonces será en la tabla Capitulos donde se almacenan datos duplicados, porque no creo que sea en la tabla Publicaciones, ya que ésta última sí dispone de su correspondiente clave principal.


    > La cuestion seria que unicamente me comparase el campo Codigotextbox.text si
    > se encuentra repetido o no.  En caso de encontrarse repetido, que no almacene
    > nada, y de no ser asi, permita el almacenamiento.

    Si te refieres al campo Codigo de la tabla Publicaciones, no tienes que comparar nada, porque si aplicas el código que te indiqué, es imposible que en el objeto DataTable existan registros duplicados, por tanto, cuando envíes dicho objeto DataTable a la base de datos, en ésta tampoco pueden existir registros duplicados, ya que la tabla Publicaciones tiene establecida una clave principal, y su motor de base de datos, va a impedir que existan registros duplicados.

    Para hacer eso, tienes que RELACIONAR las dos tablas por un campo común a ambas, que me imagino sería el campo CODIGO, de tal manera que cada uno de los registros de la tabla Capitulos se relacionase con un único registro de la tabla Publicaciones. Es decir, la tabla Publicaciones puede relacionarse con multitud de registros de la tabla Capitulos (porque una publicación puede tener varios capítulos), pero la tabla Capitulos únicamente se puede relacionar con un registro existente en la tabla Publicaciones (porque los capítulos de un libro sólo pertenecen a un libro o publicación), lo que se suele conocer como una relación de «uno a varios» entre las tablas Publicaciones y Capitulos.

    Y a la tabla Capitulos, también le tienes que establecer una clave principal, procurando que en dicha clave no participe el campo CODIGO con el cual se relaciona con la tabla Publicaciones. En esta tabla podrías crear un nuevo campo Autonumérico o Identity, que sea el que componga la clave principal de la tabla Capitulos.

    > Me.PUBLICACIONESTableAdapter.Update(Me.PUBLICACIONESDS.PUBLICACIONES)
    >
    > Me.CAPITULOSTableAdapter.Update(Me.CAPITULOSDS.CAPITULOS)

    Observo que en tu aplicación estás utilizando DOS ORÍGENES DE DATOS DISTINTOS; un origen de datos para la tabla Publicaciones (PUBLICACIONESDS) y otro distinto para la tabla Capitulos (CAPITULOSDS).

    Si utilizas dos orígenes de datos distintos, ES IMPOSIBLE RELACIONAR LAS DOS TABLAS, al menos en los orígenes de datos existentes en tu aplicación (objetos DataSet), porque que yo sepa, hasta la fecha no se pueden relacionar dos objetos DataTable existentes en diferentes objetos DataSet. Es como si quisieras relacionar dos tablas que existen en diferentes bases de datos.

    Si tanto la tabla Publicaciones como la tabla Capitulos existen en la misma base de datos, es ahí donde tienes que efectuar la relación entre ambas tablas, de tal manera que cuando crees el orígen de datos en tu proyecto, selecciones las dos tablas de la base de datos para que el propio origen de datos detecte la relación existente y la aplique en el origen de datos que deseas crear.

    ¿Que no quieres crear la relación en la propia base de datos? Entonces tendrás que crear la relación manualmente en el origen de datos del proyecto de Visual Basic. Pero para ello, TIENES QUE UTILIZAR EL MISMO ORIGEN DE DATOS que contenga a las dos tablas, porque como te he indicado anteriormente, no se puede relacionar dos objetos DataTable (dos tablas) que existen en diferentes objetos DataSet (en dos bases de datos).

    Cuando tengas creada la relación entre las dos tablas, nunca se podrán duplicar registros en la tabla Publicaciones, porque tanto el objeto DataTable como la propia tabla de la base de datos, tienen establecida una clave principal (el campo CODIGO). Y nunca se permitirá añadir un nuevo registro, o actualizar alguno existente en la tabla Capitulos, que no se relacione con ningún registro existente en la tabla Publicaciones.

    Por supuesto, en la tabla Capitulos se pueden duplicar registros, porque una publicación (un libro) puede tener varios capítulos. Por ejemplo, habrán registros que tengan el mismo CODIGO de la tabla Publicaciones, y eso es normal que así suceda. Pero si le has añadido una clave principal a la tabla Capitulos mediante un campo Autonumérico o Identity, cada uno de los registros de la tabla Capitulos serán únicos, aunque exista el mismo CODIGO en varios registros de la tabla Capitulos.

    El "truco" que te indiqué en mi primer mensaje, funciona bien cuando hablamos de un objeto DataTable existente en el origen de datos (objeto DataSet), y la tabla tiene establecida una clave principal. Pero si no se reúnen los requisitos necesarios, ¿cómo quieres que funcione? ¡En la vida funcionará! :-)

    Me parece a mí que vas a tener que diseñar primeramente la base de datos, para establecer correctamente las relaciones entre sus tablas, y vas a tener que diseñar nuevamente el origen de datos de tu proyecto, para que en UN ÚNICO ORIGEN DE DATOS coexistan ambas tablas: Publicaciones y Capitulos. Y esto ya se sale fuera del asunto por el que iniciastes ésta conversación, por lo que te aconsejaría que iniciaras nuevas conversaciones (preguntas, hilos) para las nuevas dudas o problemas que te surgan. Aparte que voy a estar de vacaciones y no sé si te voy a poder responder.

     


    Enrique Martínez [MS MVP - VB]
    Monday, August 16, 2010 4:58 AM
    Moderator
  • Enrique:

     

    Antes que nada, quiero agradecerte por toda la paciencia que has tenido conmigo, y tambien por la ayuda que en manera desinteresada me estas brindando, eso no sabes como lo aprecio y valoro. 

     

    Pasando a otra cosa, hiciste un comentari en tu anterior muy sensato, y es el siguiente:

     

    > La cuestion seria que unicamente me comparase el campo Codigotextbox.text si
    > se encuentra repetido o no.  En caso de encontrarse repetido, que no almacene
    > nada, y de no ser asi, permita el almacenamiento.

     

    Creo que si me hubiese sabido explicar desde el principio, todo se hubiera solo relacionado a esto y no tendria la necesidad de tanto codigo y tiempo de distraccion de tu persona hacia mi.

    Esto es en realidad el punto del problema, tengo que pensar como poder solucionar esta cuestion, reitero mi agradecimiento unevamente, por favor disfruta de tus vacaciones, viaja, descansa o lo que necesites, pero en verdad aprovechalas.  Espero y te encuentres bien, en caso de que no pueas responder lo entendere. Un saludo hasta donde te encuentres.

    Monday, August 16, 2010 7:15 AM