Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este tutorial se revisan los aspectos básicos del control de simultaneidad optimista y, a continuación, se explora cómo implementarlo mediante el control SqlDataSource.
Introducción
En el tutorial anterior se ha examinado cómo agregar funcionalidades de inserción, actualización y eliminación al control SqlDataSource. En resumen, para proporcionar estas características, necesitamos especificar la instrucción SQL correspondiente INSERT
, UPDATE
o DELETE
en las propiedades de los controles InsertCommand
, UpdateCommand
o DeleteCommand
, junto con los parámetros adecuados en las colecciones InsertParameters
, UpdateParameters
y DeleteParameters
. Aunque estas propiedades y colecciones se pueden especificar manualmente, el botón Avanzado del Asistente para configurar orígenes de datos ofrece una casilla Generar INSERT
, UPDATE
, y DELETE
instrucciones que crearán automáticamente estas instrucciones en función de la SELECT
instrucción.
La casilla de verificación de las instrucciones Generar INSERT
, UPDATE
y DELETE
se incluye en el cuadro de diálogo Opciones avanzadas de generación de SQL junto con una opción para Usar simultaneidad optimista (Vea Figura 1). Cuando se selecciona la opción, las WHERE
cláusulas de las instrucciones UPDATE
generadas automáticamente DELETE
se modifican para realizar únicamente la actualización o eliminación si los datos de la base de datos subyacente no se han modificado desde la última vez que el usuario cargó los datos en la rejilla.
Figura 1: Puede agregar soporte de concurrencia optimista desde el cuadro de diálogo Opciones avanzadas para la generación de SQL
En el tutorial Implementación de simultaneidad optimista , hemos examinado los aspectos básicos del control de simultaneidad optimista y cómo agregarlo a ObjectDataSource. En este tutorial, se retocan los aspectos básicos del control de simultaneidad optimista y, a continuación, se explorará cómo implementarlo mediante SqlDataSource.
Resumen de la concurrencia optimista
En el caso de las aplicaciones web que permiten a varios usuarios simultáneos editar o eliminar los mismos datos, existe la posibilidad de que un usuario sobrescriba accidentalmente otros cambios. En el tutorial Implementando Concurrencia Optimista, he proporcionado el siguiente ejemplo:
Imagine que dos usuarios, Jisun y Sam, estaban visitando una página en una aplicación que permitía a los visitantes actualizar y eliminar productos a través de un control GridView. Ambos hacen clic en el botón Editar para Chai aproximadamente al mismo tiempo. Jisun cambia el nombre del producto a Chai Tea y hace clic en el botón Actualizar. El resultado neto es una UPDATE
instrucción que se envía a la base de datos, que establece todos los campos actualizables del producto (aunque Jisun solo ha actualizado un campo, ProductName
). En este momento, la base de datos tiene los valores Té Chai, la categoría Bebidas, el proveedor Exotic Liquids, para este producto en particular. Sin embargo, el GridView en la pantalla de Sam sigue mostrando el nombre del producto en la fila editable del GridView como Chai. Unos segundos después de confirmar los cambios de Jisun, Sam actualiza la categoría a Condiments y hace clic en Actualizar. Esto da como resultado una UPDATE
instrucción enviada a la base de datos que establece el nombre del producto en Chai, al CategoryID
identificador de categoría de Condimentos correspondiente, etc. Los cambios de Jisun en el nombre del producto han sido reemplazados.
En la figura 2 se muestra esta interacción.
Figura 2: Cuando dos usuarios actualizan simultáneamente un registro, hay posibles cambios de un usuario para sobrescribir los otros (haga clic para ver la imagen de tamaño completo).
Para evitar que este escenario se materialice, se debe implementar una forma de control de simultaneidad. El enfoque de este tutorial sobre la concurrencia optimista se basa en la suposición de que, aunque puede haber conflictos de concurrencia de vez en cuando, la gran mayoría del tiempo tales conflictos no surgirán. Por lo tanto, si surge un conflicto, el control de simultaneidad optimista simplemente informa al usuario de que sus cambios no se pueden guardar porque otro usuario ha modificado los mismos datos.
Nota:
En el caso de las aplicaciones en las que se supone que habrá muchos conflictos de simultaneidad o si estos conflictos no son tolerables, se puede usar el control de simultaneidad pesimista en su lugar. Consulte el tutorial Implementación de simultaneidad optimista para obtener una explicación más exhaustiva sobre el control de simultaneidad pesimista.
El control de simultaneidad optimista funciona asegurándose de que el registro que se actualiza o elimina tiene los mismos valores que cuando se inicia el proceso de actualización o eliminación. Por ejemplo, al hacer clic en el botón Editar de una gridView editable, los valores del registro se leen de la base de datos y se muestran en cuadros de texto y otros controles web. GridView guarda estos valores originales. Más adelante, después de que el usuario realice sus cambios y haga clic en el botón Actualizar, la UPDATE
instrucción usada debe tener en cuenta los valores originales más los nuevos valores y actualizar solo el registro de base de datos subyacente si los valores originales que el usuario inició la edición son idénticos a los valores que todavía están en la base de datos. En la figura 3 se muestra esta secuencia de eventos.
Figura 3: Para que la actualización o eliminación se realice correctamente, los valores originales deben ser iguales a los valores actuales de la base de datos (haga clic para ver la imagen de tamaño completo).
Hay varios enfoques para implementar la simultaneidad optimista (consulte La lógica de actualización de simultaneidad optimista de Peter A. Bromberg para obtener una breve visión de una serie de opciones). La técnica usada por SqlDataSource (así como por los conjuntos de datos con tipo ADO.NET usadas en nuestra capa de acceso a datos) aumenta la WHERE
cláusula para incluir una comparación de todos los valores originales. La instrucción siguiente UPDATE
, por ejemplo, actualiza el nombre y el precio de un producto solo si los valores de base de datos actuales son iguales a los valores que se recuperaron originalmente al actualizar el registro en GridView. Los @ProductName
parámetros y @UnitPrice
contienen los nuevos valores especificados por el usuario, mientras @original_ProductName
que y @original_UnitPrice
contienen los valores que originalmente se cargaron en GridView cuando se hizo clic en el botón Editar:
UPDATE Products SET
ProductName = @ProductName,
UnitPrice = @UnitPrice
WHERE
ProductID = @original_ProductID AND
ProductName = @original_ProductName AND
UnitPrice = @original_UnitPrice
Como veremos en este tutorial, habilitar el control de simultaneidad optimista con SqlDataSource es tan sencillo como marcar una casilla.
Paso 1: Creación de un objeto SqlDataSource que admita la simultaneidad optimista
Para empezar, abra la OptimisticConcurrency.aspx
página desde la SqlDataSource
carpeta . Arrastre un control SqlDataSource desde el cuadro de herramientas al Diseñador y configure su ID
propiedad en ProductsDataSourceWithOptimisticConcurrency
. A continuación, haga clic en el vínculo Configurar origen de datos desde la etiqueta inteligente del control. En la primera pantalla del asistente, elija trabajar con NORTHWINDConnectionString
y haga clic en Siguiente.
Figura 4: Elegir trabajar con NORTHWINDConnectionString
(Haga clic para ver la imagen de tamaño completo)
En este ejemplo se agregará una clase GridView que permita a los usuarios editar la Products
tabla. Por lo tanto, en la pantalla Configurar la instrucción Select, elija la tabla Products
de la lista desplegable y seleccione las columnas ProductID
, ProductName
, UnitPrice
y Discontinued
, como se muestra en la figura 5.
Figura 5: En la Products
tabla, devuelve las ProductID
columnas , ProductName
, UnitPrice
y Discontinued
(haga clic para ver la imagen de tamaño completo)
Después de seleccionar las columnas, haga clic en el botón Opciones avanzadas para abrir el cuadro de diálogo Opciones avanzadas de generación de SQL. Active las casillas Generar INSERT
, UPDATE
y DELETE
y Usar simultaneidad optimista y haga clic en Aceptar (consulte la Figura 1 para una captura de pantalla). Para completar el asistente, hemos de hacer clic en Siguiente y, a continuación, en Finalizar.
Después de completar el Asistente para configurar orígenes de datos, dedique un momento a examinar las propiedades DeleteCommand
y UpdateCommand
y las colecciones DeleteParameters
y UpdateParameters
resultantes. La manera más fácil de hacerlo es hacer clic en la pestaña Origen de la esquina inferior izquierda para ver la sintaxis declarativa de la página. Allí encontrará un valor de UpdateCommand
:
UPDATE [Products] SET
[ProductName] = @ProductName,
[UnitPrice] = @UnitPrice,
[Discontinued] = @Discontinued
WHERE
[ProductID] = @original_ProductID AND
[ProductName] = @original_ProductName AND
[UnitPrice] = @original_UnitPrice AND
[Discontinued] = @original_Discontinued
Con siete parámetros en la colección UpdateParameters
.
<asp:SqlDataSource ID="ProductsDataSourceWithOptimisticConcurrency"
runat="server" ...>
<DeleteParameters>
...
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="ProductName" Type="String" />
<asp:Parameter Name="UnitPrice" Type="Decimal" />
<asp:Parameter Name="Discontinued" Type="Boolean" />
<asp:Parameter Name="original_ProductID" Type="Int32" />
<asp:Parameter Name="original_ProductName" Type="String" />
<asp:Parameter Name="original_UnitPrice" Type="Decimal" />
<asp:Parameter Name="original_Discontinued" Type="Boolean" />
</UpdateParameters>
...
</asp:SqlDataSource>
Del mismo modo, la propiedad DeleteCommand
y la colección DeleteParameters
deben tener un aspecto similar al siguiente:
DELETE FROM [Products]
WHERE
[ProductID] = @original_ProductID AND
[ProductName] = @original_ProductName AND
[UnitPrice] = @original_UnitPrice AND
[Discontinued] = @original_Discontinued
<asp:SqlDataSource ID="ProductsDataSourceWithOptimisticConcurrency"
runat="server" ...>
<DeleteParameters>
<asp:Parameter Name="original_ProductID" Type="Int32" />
<asp:Parameter Name="original_ProductName" Type="String" />
<asp:Parameter Name="original_UnitPrice" Type="Decimal" />
<asp:Parameter Name="original_Discontinued" Type="Boolean" />
</DeleteParameters>
<UpdateParameters>
...
</UpdateParameters>
...
</asp:SqlDataSource>
Además de aumentar las cláusulas WHERE
de las propiedades UpdateCommand
y DeleteCommand
(y agregar los parámetros adicionales a las colecciones de parámetros correspondientes), al seleccionar la opción Usar simultaneidad optimista se ajustan otras dos propiedades:
- Cambia la
ConflictDetection
propiedad deOverwriteChanges
(valor predeterminado) aCompareAllValues
- Cambia la
OldValuesParameterFormatString
propiedad de {0} (valor predeterminado) a original_{0} .
Cuando el control web de datos invoca el método Update()
o Delete()
de SqlDataSource, pasa los valores originales. Si la propiedad ConflictDetection
del SqlDataSource está establecida en CompareAllValues
, estos valores originales se agregan al comando. La OldValuesParameterFormatString
propiedad proporciona el patrón de nomenclatura usado para estos parámetros de valor original. El asistente para configurar el origen de datos utiliza original_{0} y asigna nombres a cada parámetro original en las propiedades UpdateCommand
y DeleteCommand
, y en las colecciones UpdateParameters
y DeleteParameters
respectivamente.
Nota:
Puesto que no estamos utilizando las capacidades de inserción del control SqlDataSource, puede eliminar la propiedad InsertCommand
y su colección InsertParameters
si lo desea.
Manejo correcto deNULL
valores
Desafortunadamente, las instrucciones aumentadas UPDATE
y DELETE
generadas automáticamente por el Asistente para configurar orígenes de datos al usar la simultaneidad optimista no funcionan con registros que contienen NULL
valores. Para ver por qué, considere nuestra SqlDataSource UpdateCommand
:
UPDATE [Products] SET
[ProductName] = @ProductName,
[UnitPrice] = @UnitPrice,
[Discontinued] = @Discontinued
WHERE
[ProductID] = @original_ProductID AND
[ProductName] = @original_ProductName AND
[UnitPrice] = @original_UnitPrice AND
[Discontinued] = @original_Discontinued
La UnitPrice
columna de la Products
tabla puede tener NULL
valores. Si un registro determinado tiene un NULL
valor para UnitPrice
, la parte WHERE
de la [UnitPrice] = @original_UnitPrice
cláusula siempre se evaluará como False porque NULL = NULL
siempre devuelve False. Por lo tanto, los registros que contienen NULL
valores no se pueden editar ni eliminar, ya que las UPDATE
cláusulas y DELETE
WHERE
no devolverán ninguna fila para actualizar o eliminar.
Nota:
Este error se informó por primera vez a Microsoft en junio de 2004 en SqlDataSource genera instrucciones SQL incorrectas y se programa para corregirse en la próxima versión de ASP.NET.
Para corregir esto, tenemos que actualizar manualmente las WHERE
cláusulas en ambas propiedades UpdateCommand
y DeleteCommand
de todas las columnas que pueden tener valores. En general, cambie [ColumnName] = @original_ColumnName
a:
(
([ColumnName] IS NULL AND @original_ColumnName IS NULL)
OR
([ColumnName] = @original_ColumnName)
)
Esta modificación se puede realizar directamente a través del marcado declarativo, a través de las opciones UpdateQuery o DeleteQuery de la ventana Propiedades, o a través de las pestañas UPDATE y DELETE de la opción Especificar una instrucción SQL personalizada o un procedimiento almacenado en el Asistente para configurar orígenes de datos. De nuevo, esta modificación debe realizarse para cada columna en las cláusulas UpdateCommand
, DeleteCommand
y WHERE
que puedan contener valores NULL
.
Aplicar esto a nuestro ejemplo da como resultado los siguientes valores modificados UpdateCommand
y DeleteCommand
:
UPDATE [Products] SET
[ProductName] = @ProductName,
[UnitPrice] = @UnitPrice,
[Discontinued] = @Discontinued
WHERE
[ProductID] = @original_ProductID AND
[ProductName] = @original_ProductName AND
(([UnitPrice] IS NULL AND @original_UnitPrice IS NULL)
OR ([UnitPrice] = @original_UnitPrice)) AND
[Discontinued] = @original_Discontinued
DELETE FROM [Products]
WHERE
[ProductID] = @original_ProductID AND
[ProductName] = @original_ProductName AND
(([UnitPrice] IS NULL AND @original_UnitPrice IS NULL)
OR ([UnitPrice] = @original_UnitPrice)) AND
[Discontinued] = @original_Discontinued
Paso 2: Agregar un control GridView con opciones de edición y eliminación
Con SqlDataSource configurado para admitir la simultaneidad optimista, todo lo que queda es agregar un control web de datos a la página que utiliza este control de simultaneidad. En este tutorial, vamos a agregar una clase GridView que proporciona funciones de edición y eliminación. Para lograr esto, arrastre un GridView desde el cuadro de herramientas al diseñador y configúrelo en ID
Products
. Desde la etiqueta inteligente de GridView, vincúlelo al control SqlDataSource agregado en el paso 1 ProductsDataSourceWithOptimisticConcurrency
. Por último, active las opciones Habilitar edición y Habilitar eliminación de la etiqueta inteligente.
Figura 6: Enlazar GridView a SqlDataSource y Habilitar edición y eliminación (haga clic para ver la imagen de tamaño completo)
Después de agregar GridView, configure su apariencia quitando BoundField ProductID
, cambiando la ProductName
propiedad BoundField s HeaderText
a Product y actualizando BoundField UnitPrice
para que su HeaderText
propiedad sea simplemente Price. Idealmente, mejoraríamos la interfaz de edición para incluir un RequiredFieldValidator para el ProductName
valor y un CompareValidator para el UnitPrice
valor (para asegurarse de que es un valor numérico con formato correcto). Consulte el tutorial Personalización de la interfaz de modificación de datos para obtener un vistazo más detallado a la personalización de la interfaz de edición de GridView.
Nota:
El estado de vista de GridView debe estar habilitado, ya que los valores originales pasados de GridView a SqlDataSource se almacenan en estado de vista.
Después de realizar estas modificaciones en el GridView, el marcado declarativo de el GridView y el SqlDataSource debe verse como el siguiente:
<asp:SqlDataSource ID="ProductsDataSourceWithOptimisticConcurrency"
runat="server" ConflictDetection="CompareAllValues"
ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
DeleteCommand=
"DELETE FROM [Products]
WHERE [ProductID] = @original_ProductID
AND [ProductName] = @original_ProductName
AND (([UnitPrice] IS NULL AND @original_UnitPrice IS NULL)
OR ([UnitPrice] = @original_UnitPrice))
AND [Discontinued] = @original_Discontinued"
OldValuesParameterFormatString=
"original_{0}"
SelectCommand=
"SELECT [ProductID], [ProductName], [UnitPrice], [Discontinued]
FROM [Products]"
UpdateCommand=
"UPDATE [Products]
SET [ProductName] = @ProductName, [UnitPrice] = @UnitPrice,
[Discontinued] = @Discontinued
WHERE [ProductID] = @original_ProductID
AND [ProductName] = @original_ProductName
AND (([UnitPrice] IS NULL AND @original_UnitPrice IS NULL)
OR ([UnitPrice] = @original_UnitPrice))
AND [Discontinued] = @original_Discontinued">
<DeleteParameters>
<asp:Parameter Name="original_ProductID" Type="Int32" />
<asp:Parameter Name="original_ProductName" Type="String" />
<asp:Parameter Name="original_UnitPrice" Type="Decimal" />
<asp:Parameter Name="original_Discontinued" Type="Boolean" />
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="ProductName" Type="String" />
<asp:Parameter Name="UnitPrice" Type="Decimal" />
<asp:Parameter Name="Discontinued" Type="Boolean" />
<asp:Parameter Name="original_ProductID" Type="Int32" />
<asp:Parameter Name="original_ProductName" Type="String" />
<asp:Parameter Name="original_UnitPrice" Type="Decimal" />
<asp:Parameter Name="original_Discontinued" Type="Boolean" />
</UpdateParameters>
</asp:SqlDataSource>
<asp:GridView ID="Products" runat="server"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="ProductsDataSourceWithOptimisticConcurrency">
<Columns>
<asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
<asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
<asp:BoundField DataField="UnitPrice" HeaderText="Price"
SortExpression="UnitPrice" />
<asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued"
SortExpression="Discontinued" />
</Columns>
</asp:GridView>
Para ver el control de simultaneidad optimista en acción, abra dos ventanas del navegador y cargue la OptimisticConcurrency.aspx
página en ambas. Haga clic en los botones de edición para el primer producto en ambos navegadores. En un explorador, cambie el nombre del producto y haga clic en Actualizar. El explorador realizará un postback y el GridView volverá a su modo previo a la edición, mostrando el nuevo nombre del producto para el registro recién editado.
En la segunda ventana del explorador, cambie el precio (pero deje el nombre del producto como su valor original) y haga clic en Actualizar. Durante la devolución de datos, la tabla vuelve a su modo anterior a la edición, pero el cambio en el precio no se registra. El segundo explorador muestra el mismo valor que el primero con el nuevo nombre del producto con el precio anterior. Los cambios realizados en la segunda ventana del explorador se perdieron. Además, los cambios se perdieron de manera bastante silenciosa, ya que no había ninguna excepción o mensaje que indicara que se acaba de producir una violación de concurrencia.
Figura 7: Los cambios en la segunda ventana del explorador se perdieron silenciosamente (haga clic para ver la imagen de tamaño completo)
La razón por la que no se confirmaron los cambios del segundo navegador fue porque la cláusula de la instrucción UPDATE
WHERE
filtraba todos los registros y, por lo tanto, no afectaba a ninguna fila. Echemos un vistazo a la UPDATE
instrucción de nuevo:
UPDATE [Products] SET
[ProductName] = @ProductName,
[UnitPrice] = @UnitPrice,
[Discontinued] = @Discontinued
WHERE
[ProductID] = @original_ProductID AND
[ProductName] = @original_ProductName AND
(([UnitPrice] IS NULL AND @original_UnitPrice IS NULL) OR
([UnitPrice] = @original_UnitPrice)) AND
[Discontinued] = @original_Discontinued
Cuando la segunda ventana del explorador actualiza el registro, el nombre del producto original especificado en la WHERE
cláusula no coincide con el nombre de producto existente (ya que el primer explorador cambió). Por lo tanto, la instrucción [ProductName] = @original_ProductName
devuelve False y UPDATE
no afecta a ningún registro.
Nota:
Eliminar funciona de la misma manera. Con dos ventanas del explorador abiertas, empiece editando un producto determinado con uno y, a continuación, guardando sus cambios. Después de guardar los cambios en un explorador, haga clic en el botón Eliminar del mismo producto en el otro. Dado que los valores originales no coinciden en la cláusula DELETE
de la instrucción WHERE
, la eliminación falla silenciosamente.
Desde la perspectiva del usuario final en la segunda ventana del explorador, después de hacer clic en el botón Actualizar, la cuadrícula vuelve al modo de edición previa, pero se perdieron sus cambios. Sin embargo, no hay indicadores visuales para indicar que sus cambios no se han aplicado. Idealmente, si los cambios de un usuario se pierden debido a un conflicto de simultaneidad, se le notificaría al usuario y, quizás, se mantendría la cuadrícula en modo de edición. Veamos cómo hacerlo.
Paso 3: Determinar cuándo ha ocurrido una violación de concurrencia
Dado que una infracción de simultaneidad rechaza los cambios realizados, sería agradable avisar al usuario cuando se ha producido una infracción de simultaneidad. Para alertar al usuario, vamos a agregar un control Web label a la parte superior de la página denominada ConcurrencyViolationMessage
cuya Text
propiedad muestra el siguiente mensaje: Ha intentado actualizar o eliminar un registro que otro usuario actualizó simultáneamente. Revise los cambios del otro usuario y vuelva a actualizar o eliminar. Establezca la propiedad del control de etiqueta CssClass
a Warning, que es una clase CSS definida en Styles.css
que muestra el texto en una fuente roja, cursiva, negrita y grande. Por último, establezca las propiedades Label s Visible
y EnableViewState
en False
. Esto ocultará la etiqueta, excepto en aquellos postbacks donde se establezca explícitamente la propiedad Visible
a True
.
Figura 8: Agregar un control etiqueta a la página para mostrar la advertencia (haga clic para ver la imagen de tamaño completo)
Al realizar una actualización o eliminación, los controladores de eventos RowUpdated
y RowDeleted
de GridView se activan después de que su control de origen de datos haya realizado la actualización o eliminación solicitadas. Podemos determinar cuántas filas se vieron afectadas por la operación de estos controladores de eventos. Si se han afectado cero filas, queremos mostrar la ConcurrencyViolationMessage
etiqueta.
Cree un controlador de eventos para los RowUpdated
eventos y RowDeleted
agregue el código siguiente:
Protected Sub Products_RowUpdated(sender As Object, e As GridViewUpdatedEventArgs) _
Handles Products.RowUpdated
If e.AffectedRows = 0 Then
ConcurrencyViolationMessage.Visible = True
e.KeepInEditMode = True
' Rebind the data to the GridView to show the latest changes
Products.DataBind()
End If
End Sub
Protected Sub Products_RowDeleted(sender As Object, e As GridViewDeletedEventArgs) _
Handles Products.RowDeleted
If e.AffectedRows = 0 Then
ConcurrencyViolationMessage.Visible = True
End If
End Sub
En ambos controladores de eventos comprobamos la propiedad e.AffectedRows
y, si es igual a 0, establecemos la propiedad ConcurrencyViolationMessage
Label Visible
en True
. En el RowUpdated
controlador de eventos, también indicamos a GridView que permanezca en modo de edición estableciendo la KeepInEditMode
propiedad en true. Al hacerlo, es necesario volver a vincular los datos a la cuadrícula para que los datos del otro usuario se carguen en la interfaz de edición. Esto se logra llamando al método GridView s DataBind()
.
Como se muestra en la figura 9, con estos dos controladores de eventos, se muestra un mensaje muy notable cada vez que se produce una infracción de simultaneidad.
Figura 9: Se muestra un mensaje ante una infracción de simultaneidad (haga clic para ver la imagen de tamaño completo)
Resumen
Al crear una aplicación web donde varios usuarios simultáneos pueden editar los mismos datos, es importante tener en cuenta las opciones de control de simultaneidad. De forma predeterminada, los controles web de datos ASP.NET y los controles de origen de datos no emplean ningún control de simultaneidad. Como vimos en este tutorial, la implementación del control de simultaneidad optimista con SqlDataSource es relativamente rápida y fácil. SqlDataSource maneja la mayor parte del trabajo para agregar cláusulas aumentadas WHERE
a las instrucciones UPDATE
y DELETE
generadas automáticamente, pero hay algunas sutilezas en el control de columnas de valor NULL
, como se describe en la sección de manejo correcto de valores NULL
.
Este tutorial concluye nuestro examen de SqlDataSource. Nuestros tutoriales restantes volverán a trabajar con datos mediante ObjectDataSource y la arquitectura en capas.
¡Feliz programación!
Acerca del autor
Scott Mitchell, autor de siete libros de ASP/ASP.NET y fundador de 4GuysFromRolla.com, ha estado trabajando con tecnologías web de Microsoft desde 1998. Scott trabaja como consultor independiente, entrenador y escritor. Su último libro es Sams Teach Yourself ASP.NET 2.0 en 24 horas. Se puede contactar con él en mitchell@4GuysFromRolla.com.