Digamos que tengo una docena de tablas con la misma estructura: 3 campos (Id para la clave primaria, Nombre y Descripción) con las mismas características. Estas tablas, además, van a tener pocos registros, no llegarán a 20. Concretamente, forman parte de una base de datos de series y películas y almacenan los datos de, por ejemplo, códecs, formatos de archivo, resoluciones, el soporte (DVD, CD, disco duro) donde están almacenados, etc. La pregunta es ¿cómo gestiono el contenido de estas tablas (altas, bajas y modificaciones)? A cada cual se le ocurrirá una opción, la mía, con pocas ganas de complicarme la vida, es la siguiente:
Tengo un formulario sencillo con los siguientes elementos: un ListBox que mostrará el nombre de todos los elementos de la tabla y servirá para navegar por los registros, dos TextBox, uno para el Nombre y otro para la Descripción, con sus respectivas etiquetas, y los controles necesarios para la gestión (podrían ser botones, pero yo uso un MenuStrip): Nuevo, Modificar, Eliminar, Aceptar y Cancelar. Añadimos un BindingSource a la ecuación y, si nos olvidamos por el momento de la generación de la clave primaria, esto ya está hecho, independientemente de lo que pongamos debajo del BindingSource.
Por otro lado, tengo 12 datasets tipados, cada uno con una de las tablas en cuestión. Tienen una pequeña personalización adicional: se controla el evento TableNewRow para generar de forma automática la clave primaria de la nueva fila.
Volviendo al formulario, quiero poder elegir la tabla que se muestra en él. Para ello se me ocurre poner un ComboBox con la lista de tablas, de forma que al elegir una de ellas se carguen y muestren los datos en el formulario. Así que la dificultad real del formulario se reduce a lo que pasa en el ComboBox. Básicamente, lo que necesito es controlar el evento SelectedIndexChanged para cargar los datos de la tabla elegida y cambiar el título del formulario y algunas etiquetas por los relativos a la tabla. Así que el siguiente paso es ¿qué meto en el ComboBox?
Necesito identificar la tabla, lo que puedo hacer con una enumeración (llamémosla enTablas). Necesito mostrar un nombre en el Combo, por lo que necesito una cadena de texto. Esta cadena puedo usarla para el título del formulario o puede que necesite otras. Ahora junto todo esto en una clase o estructura y, si quiero mostrar las tablas ordenadas en el Combo, puedo implementar la interface IComparable. En fin, algo así:
Private Class MisTablas Implements IComparable(Of MisTablas) Private _IdTabla As enTablas Private _Nombre As String Public Sub New(ByVal tabla As enTablas, _ ByVal NombreTabla As String) _IdTabla = tabla _Nombre = NombreTabla End Sub Public ReadOnly Property Nombre() As String Get Return _Nombre End Get End Property Public ReadOnly Property IdTabla() As enTablas Get Return _IdTabla End Get End Property Public Function CompareTo(ByVal other As MisTablas) _ As Integer Implements _ System.IComparable(Of MisTablas).CompareTo Return Me._Nombre.CompareTo(other.Nombre) End Function End Class |
En el constructor del formulario puedo llenar una List(of MisTablas) con los datos de todas las tablas y volcarlo al ComboBox (mediante su DataSource, su DisplayMember y su ValueMember). Así, en el SelectedIndexChanged (bueno, hablando con propiedad, en el método que controla ese evento) puedo obtener el ítem seleccionado del Combo, que será del tipo MisTablas, y obtener todos los datos necesarios. Lo siguiente es leer los datos de la tabla.
Como trabajo con DataSet añado al formulario un DataSet genérico, digamos que dsTablas. Este DataSet es el origen de datos del BindingSource bsTablas. En cada cambio de tabla lo que haremos será: desligar la tabla de los controles, limpiando los bindings. A continuación, tiraremos el dataset a la basura y obtendremos otro con los datos nuevos desde la clase de acceso a datos. Por último, volvemos a enlazar todo. O sea, esto:
With Me 'limpiamos los bindings .txtComentarios.DataBindings.Clear() .txtDescriptor.DataBindings.Clear() 'leemos datos .dsTablas.Dispose() .dsTablas = .TablasMenores.LeerDatos(._TablaElegida) 'ligamos los controles .bsTablas.DataSource = .dsTablas.Tables(0) .txtDescriptor.DataBindings.Add(New Binding("text", _ .bsTablas, "Nombre")) .txtComentarios.DataBindings.Add(New Binding("text", _ .bsTablas, "Descripcion")) .lstNavegacion.DataSource = .bsTablas .lstNavegacion.DisplayMember = "Nombre" End With |
TablasMenores es la clase de acceso a datos y LeerDatos es una función que devuelve un DataSet genérico. Como puede verse, recibe un parámetro. Este, del tipo enTablas, indica la tabla que debe leer de la base de datos. Internamente, la clase de acceso a datos dispone de tantos métodos privados de lectura de datos como tablas hay. Cada uno devuelve el DataSet tipado correspondiente. La función pública LeerDatos usa el clásico Select Case para llamar al método privado correspondiente, coge el DataSet tipado que le devuelven y lo manda acá como DataSet genérico.
Así pues, aunque en el formulario tengamos un DataSet genérico, realmente estamos trabajando con el DataSet tipado de la tabla que tengamos elegida. La ventaja que le veo a esto es que el código del formulario queda muy sencillo pero podemos aprovecharnos de todo el código personalizado que queramos meter en los DataSet tipados. En este caso, sólo aprovecho para generar la clave primaria, pero podría tener validación de datos propia o qué se yo.
Como siempre, habrá métodos más simples y elegantes de hacerlo, pero este ha sido el mío.
interesante, yo tambien estoy haciendo lo mismo, tengo 8 tablas y quiero seleccionarlas con un combobox para hacer las operaciones de listar, modificar, eliminar, actualizar, etc…pero aun no lo consigo, esto trabajando con C#, y BD Postgresql…..desde luego te agradesco por la ayuda..
saludos