Supongamos que tenemos una relación n:m facilita. Por ejemplo, series y los géneros de estas series. Digamos que tengo mi tabla de series con su clave primaria IdSeries, mi tabla de géneros con su clave IdGenero y la otra que tiene únicamente los campos IdSerie e IdGenero para hacer la relación. Digamos también que quiero mostrar los géneros de cada serie en un ListBox, que llamaremos lstGeneros. Y digamos, de paso, que quiero usar ese ListBox no sólo para mostrar los géneros de la serie, sino también para seleccionarlos en altas y modificaciones. Uhm, ya la cosa se complica.
Vayamos por partes: visualización. Esto es lo más fácil y hay opciones para todos los gustos. Por ejemplo, podría generar una vista en la base de datos que me englobase las tablas de género y «géneros de series» y montar un dataset tipado con la tabla de series, la vista y la relación entre ambas. De ahí a montar un maestro-detalle de tutorial, sólo que con un listbox en lugar de un datagridview, sólo hay un paso.
Podría tener un dataset tipado con las tres tablas completas y cargadas en memoria y usar una consulta LINQ para sacar un listado de los IdGenero y géneros y ligarla al listbox cada vez que cambie de serie. Podría hacer la consulta a la base de datos en cada cambio de series. Podría, ¡qué sé yo!, usar LINQ to SQL.
Para las altas también es fácil: muestro en el listbox toda la tabla de géneros y permito la selección múltiple. Por supuesto, como ValueMember tengo el IdGenero. Al aceptar la nueva alta sólo tengo que recorrer el listbox, coger los IdGenero de los géneros seleccionados, coger el IdSerie de la nueva serie y crear las nuevas filas de la tabla «géneros de series» con estos valores. Luego, a guardar todo.
El problema viene con las modificaciones. Para empezar, tengo que marcar los géneros ya existentes para esa serie. Ahora el problema es que el usuario puede tanto marcar géneros nuevos como desmarcar algunos previamente existentes. Uff. En fin, como ejemplo, supongamos que trabajo con un dataset tipado con las tres tablas, Series, GeneroSerie y Generos. Primero necesitamos coger los IdGenero de los elementos marcados en el lstGeneros. También necesitamos los géneros de la serie previamente existentes. Digamos que los obtengo así:
Dim Generos As New List(Of Integer) For i As Integer = 0 To lstGeneros.Items.Count - 1 If Me.lstGeneros.GetSelected(i) Then Generos.Add(CInt(TryCast(Me.lstGeneros.Items(i), _ DataRowView).Item(0))) End If Next Dim GenerosPrevios = From e In Me.dsSeries.GeneroSerie _ Where e.IdSerie = Me._SerieActual |
Con esto ya podemos trabajar. Primero, buscamos los géneros nuevos y los añadimos a la tabla GeneroSerie.
Dim Encontrado As Boolean = False Dim GenerosATrabajar As New List(Of Integer) For Each Genero In Generos 'Géneros marcados en el ListBox For Each Fila In GenerosPrevios Encontrado = (Fila.IdGenero = Genero) If Encontrado Then Exit For Next If Not Encontrado Then 'añadimos fila GenerosATrabajar.Add(Genero) End If Next Dim rwNuevoGeneroSerie As SeriesDataSet.GeneroSerieRow For Each Genero In GenerosATrabajar rwNuevoGeneroSerie = _dsSeries.GeneroSerie. _ NewGeneroSerieRow rwNuevoGeneroSerie.IdGenero = Genero rwNuevoGeneroSerie.IdSerie = Me._SerieActual _dsSeries.GeneroSerie.AddGeneroSerieRow( _ rwNuevoGeneroSerie) Next |
Y luego hacemos lo contrario, buscamos los que se han desmarcado, que tendremos que borrar:
GenerosATrabajar.Clear() For Each Fila In GenerosPrevios For Each Genero In Generos Encontrado = (Fila.IdGenero = Genero) If Encontrado Then Exit For Next If Not Encontrado Then 'Nos quedamos con el idGenero para borrarlo GenerosATrabajar.Add(Fila.IdGenero) 'Hay que borrar la fila, pero así no podemos 'porque afectamos a las filas de GenerosPrevios 'y se joroba el foreach, 'así que apuntamos los generos y lo hacemos luego End If Next For Each Genero In GenerosATrabajar _dsSeries.GeneroSerie.FindByIdGeneroIdSerie(Genero, _ Me._SerieActual).Delete() Next |
Nos quedaría guardarlo todo en la base de datos y listo. La utilidad de esto es relativa: en el momento en que tengamos que mostrar más de un campo, el listbox no nos vale. De igual modo, si la tabla Géneros tiene demasiados registros, va a ser confuso mostrarlos todos en un listbox y quizás sea más práctico un formulario de búsqueda o cualquier otra forma que se nos ocurra. Pero para mí, en este caso, y en otros pocos más en donde lo he empleado, me parece una buena solución.
Pingback: Quemando Cromo » Blog Archive » Jugando con DataTables