Hace unas semanas hablé de usar valores timestamp para controlar la versión del registro de cara a controlar a su vez los problemas de concurrencia, para actualizar datos, etc. Hoy voy a dar un posible uso a todo eso, usando dataset tipados. Vamos a trabajar con una tabla de ejemplo. Supongamos que:
-
La tabla en cuestión tiene definida una columna, Control, del tipo timestamp.
-
En el TableAdapter correspondiente hemos añadido dos consultas: una que nos recupera el MAX(Control) de la tabla (el valor más alto de control) y otra que nos devuelve las filas actualizadas desde que obtuvimos ese MAX(Control), o sea, aquellas cuyo valor timestamp sea mayor que el que tenemos guardado.
Con esto ya hecho, lo siguiente podría ser guardar ese valor de control que hemos obtenido de la base de datos. El mejor sitio, la misma DataTable.
Partial Class MaterialDataTable Private _MiVersion As Byte() Public Property NumVersion() As Byte() Get Return _MiVersion End Get Set(ByVal value As Byte()) _MiVersion = value End Set End Property End Class |
Tenemos dos métodos Fill, el general y el que carga las filas actualizadas. Estaría bien saber cuándo usar uno u otro. ¿Quizás una propiedad Actualizar en el mismo DataTable que nos lo indique?
Private _Actualizar As Boolean = False ''' <summary> ''' Indica si hay que actualizar la datatable usando el valor del ''' timestamp o bien cargarla entera en una operación de lectura ''' </summary> Public Property Actualizar() As Boolean Get Return Me._Actualizar End Get Set(ByVal value As Boolean) Me._Actualizar = value End Set End Property |
¿Por qué guardar esta opción? En mi caso, porque tengo un método llamado LeerDatos se limita a llenar el DataSet que le mandan con lo que devuelve el (o los) TableAdapter. Bueno, y a abrir y cerrar la conexión si es necesario, controlar las excepciones y alguna que otra cosa. Y así me ahorro el tener dos métodos que hagan lo mismo, uno para la lectura general y otro para los valores actualizados (o, si seguimos aumentando, uno para cada consulta). También podría tener el valor de Actualizar aparte y pasarlo como parámetro, pero como es un valor que atañe únicamente al DataTable, mejor que vaya con él.
También podemos ahorrar a LeerDatos el tener que discriminar entre un método Fill u otro y añadir un método en el TableAdapter que se encargue de ello.
Namespace MaterialDataSetTableAdapters Partial Class MaterialTableAdapter Public Function LeerMaterial(ByVal dtMaterial As _ MaterialDataSet.MaterialDataTable) As Integer Dim Result As Integer Try If dtMaterial.Actualizar = True Then Result = Me.FillActualizados(dtMaterial, _ dtMaterial.NumVersion) Else Result = Me.Fill(dtMaterial) End If dtMaterial.NumVersion = Me.TimestampActual Catch ex As Exception Throw ex End Try Return Result End Function End Class End Namespace |
El uso que le quiero dar a esto es el siguiente: tengo mi DataSet en memoria. En un momento dado, quiero conectarme a la base de datos, traer los datos actualizados, y sólo esos, y combinarlos con los que ya tengo. Para combinarlos usaré el método Merge que trae el propio DataSet. Ah, cachis, lo que pasa es que así tengo que hacerlo en dos pasos, primero el Merge y luego pasarle el nuevo valor de control. Podría sobrecargar el método Merge para que me haga eso de un tirón, ¿no?
Public Overloads Sub Merge(ByVal dsMaterial As MaterialDataSet) Try MyBase.Merge(dsMaterial) Me.Material.Actualizar = False Me.Material.NumVersion = dsMaterial.Material.NumVersion Catch ex As Exception Throw ex End Try End Sub |
En fin, probando cositas y dándole juego a los datasets.