** NORMAS DEL FORO **
Inicio del foro Inicio del foro > Access y VBA > Access y Otros sistemas
  Mensajes nuevos Mensajes nuevos RSS - Error de acceso simultáneo a datos
  Preguntas frecuentes Preguntas frecuentes  Buscar en el foro   Eventos   Registro Registro  Iniciar sesion Iniciar sesion

Error de acceso simultáneo a datos

 Responder Responder
Autor
Mensaje
naiki Ver desplegable
Nuevo
Nuevo
Avatar

Unido: 26/Febrero/2018
Localización: Madrid
Estado: Sin conexión
Puntos: 7
Opciones de entrada Opciones de entrada   Gracias (0) Gracias(0)   Cita naiki Cita  ResponderRespuesta Enlace directo a este mensaje Tema: Error de acceso simultáneo a datos
    Enviado: 26/Febrero/2018 a las 16:25
¡Saludos a todos los foreros!

A pesar de que he estado buscando respuesta a mi pregunta, no he podido encontrarla. Si está de hecho respondida, lamento la molestia y agradeceré que me remitan al hilo correspondiente.

Me estreno con esta pregunta. Soy programador aficionado y totalmente autodidacta. Estoy realizando una aplicación de base de datos para una asociación de padres de una enfermedad rara, y, por supuesto, de forma totalmente gratuita. Perdonadme por favor si digo o expongo cualquier barrabasada a ojos de un desarrollador profesional o experto.

La pregunta es algo genérica, más que un ejemplo concreto de código que no funciona.

La aplicación que diseño consiste en un servidor mysql en la nube. La aplicación cliente corre en Access 2007. Cuando se abre la aplicación y se piden los datos de login, se realiza una conexión a la base de datos en una procedimiento escrito en un módulo tal que así:

Public Function EstablecerConexion() As Boolean

Dim controlador As String
Dim servidor As String
Dim puerto As String
Dim dbase As String
Dim ulog As String
Dim upwd As String
Dim cadena As String
Dim conexion As ADODB.Connection

On Error GoTo err_conexion
DoCmd.Hourglass (True)

controlador = "{MySQL ODBC 5.3 ANSI Driver}"
'servidor = "IP servidor"


puerto = "puerto"
'dbase = "nombre database"
ulog = glUser
upwd = glPwd

EstablecerConexion = False

If ((ulog <> "") And (upwd <> "")) Then
    'verificar que el usuario y contraseña son válidos
    Set conexion = New ADODB.Connection
    cadena = "DRIVER= " & controlador & _
        "; SERVER=" & servidor & _
        ";DATABASE=" & dbase & _
        ";UID=" & ulog & _
        ";PWD=" & upwd
    conexion.ConnectionString = cadena
    conexion.Open
Else
    MsgBox ("El usuario y/o contraseña no pueden estar vacíos")
End If

salir:
DoCmd.Hourglass (False)
Exit Function

err_conexion:
DoCmd.Hourglass (False)
EstablecerConexion = False
Exit Function

End Function


La cuestión es que en ocasiones necesito modificar un campo del conjunto completo de registros abiertos en un formulario. Para ello, he probado diferentes alternativas:

1) abrir un recordset DAO y recorrerlo modificando el campo en cuestión

    Set rs = Me.RecordsetClone
    rs.MoveFirst
    Do While Not rs.EOF
        rs.Edit
        rs("estado") = "C"
        rs("pagado") = rs("cantidad")
        rs.Update
        rs.MoveNext
    Loop
    rs.close

Esta manera funciona, pero parece que genera mucho tráfico en la red y resulta muy lenta en cuanto el formulario contiene un número elevado de registros.

2) A través de un recordset ADO del siguiente modo:
- construir la sentencia sql a través de la propiedad <me.recordsource> y <me.filter>.
- desconectar el recordset (ADOrecordset.ActiveConnection = Nothing)
- recorrer el recordset modificando el campo requerido
- reconectar el recordset (ADOrecordset.ActiveConnection = CurrentProject.Connection)
- Actualizar (ADOrecordset.UpdateBatch)

Para ello, establezco el cursorlocation como "adUseClient" y el lock property como adLockBatchOptimistic.

Este método es algo más rápido que el anterior, pero en ocasiones da fallo de dos usuarios tratando de acceder a la base de datos al mismo tiempo.

3) Modificar la tabla de la base de datos directamente mediante sentencias sql. El código sería algo así:

Private Sub ModificarTabla

Dim ADOrs As New ADODB.Recordset
Dim Con As ADODB.Connection
Dim sql as String, sql1 As String, sql2 As String, filtro As String, filtrooriginal as String
Dim contador As Long, registros As Long

On Error GoTo err_handler

Set Con = CurrentProject.Connection
sql = Me.Recordsource
'construir la sentencia sql con el filtro que esté activo
If Not IsNull(Me.Filter) Then
    'añadir el filtro activo; primero adaptar el texto del filtro para constituir una cadena sql válida
    filtrooriginal = Me.Filter
    filtro = Replace(Me.Filter, """", "'") 'reemplazar comillas dobles por comillas simples
    filtro = " WHERE " & filtro
Else
    filtro = ""
    filtrooriginal= ""
End If

'por alguna razón que desconozco, tengo que ejecutar cada actualización de campo en sentencia separada
'si se hace junto, el campo pagado no se actualiza
sql1 = "UPDATE tabla1 SET campo1='valor1'" & filtro ' & ";"
sql2 = "UPDATE tabla1 SET campo2='valor2'" & filtro & ";"

'establecer el origen del formulario en ""
Me.recordsource = ""

'modificar la tabla
Set ADOrs = Con.Execute(sql1, contador)
ADOrs.Close
Set ADOrs = Con.Execute(sql2, contador)

'recuperar el origen del formulario
Me.Recordsource = sql
Me.Filter = formFiltro 'variable pública que contiene el valor del filtro del formulario
Me.Requery

MsgBox "Se modificaron " & contador & " registros.", vbExclamation


limpieza:
Set ADOrs = Nothing
Con.Close
Set Con = Nothing

Exit Sub

err_handler:
MsgBox "Se ha producido un error. Consulte con el administrador." & Chr(13) & "Código Error: " & Err.Number & Chr(13) & "Descripción del error: " & Err.Description, vbOKOnly
GoTo limpieza


End Sub


Este método es el más rápido, pero da también en la mayoría de las ocasiones error de que otro usuario está intentando modificar los mismos datos que usted al mismo tiempo. A veces, después de modificar algún dato del formulario, se ejecuta sin errores.

Por si es de relevancia, el formulario es un un formulario continuo cuyo origen de datos es una consulta del tipo "SELECT tabla1.campo_1,... tabla1.campo_n,..., tabla2.campo_1,...,tabla2.campo_m FROM tabla1 LEFT JOIN tabla2 ON tabla1.campo_i = tabla2.campo_j"

La propiedad "Bloqueos del registro" del formulario está en "Sin bloquear", aunque he probado poniéndola a "Registro modificado" y se comporta de la misma forma.


¿Alguna manera de atacar la cuestión y evitar estos errores de acceso simultáneo a los datos?

Gracias.


Arriba
raipon Ver desplegable
Moderador
Moderador


Unido: 10/Diciembre/2004
Localización: Desconocida
Estado: Sin conexión
Puntos: 4003
Opciones de entrada Opciones de entrada   Gracias (0) Gracias(0)   Cita raipon Cita  ResponderRespuesta Enlace directo a este mensaje Enviado: 26/Febrero/2018 a las 21:35
Hola, en primer lugar preguntar si efectivamente puede haber varios usuarios intentando modificar el mismo registro a la vez.

Saludos.
Ramon desde Terrassa.

Mi blog
Arriba
naiki Ver desplegable
Nuevo
Nuevo
Avatar

Unido: 26/Febrero/2018
Localización: Madrid
Estado: Sin conexión
Puntos: 7
Opciones de entrada Opciones de entrada   Gracias (0) Gracias(0)   Cita naiki Cita  ResponderRespuesta Enlace directo a este mensaje Enviado: 26/Febrero/2018 a las 21:58
Publicado originalmente por raipon raipon escribió:

Hola, en primer lugar preguntar si efectivamente puede haber varios usuarios intentando modificar el mismo registro a la vez.

Saludos.

No, imposible. En entorno de desarrollo sólo puedo conectarme yo.
Arriba
naiki Ver desplegable
Nuevo
Nuevo
Avatar

Unido: 26/Febrero/2018
Localización: Madrid
Estado: Sin conexión
Puntos: 7
Opciones de entrada Opciones de entrada   Gracias (0) Gracias(0)   Cita naiki Cita  ResponderRespuesta Enlace directo a este mensaje Enviado: 27/Febrero/2018 a las 12:42
He hecho progresos para determinar el problema.
La sentencia sql que está generando el error es del tipo:

sql1 = "UPDATE tabla1 SET campo1='valor1'" & filtro ' & ";"

cuando valor1 se refiere a un campo de la misma tabla, es decir, en realidad, sería así:

sql1 = "UPDATE tabla1 SET tabla1.campo1=tabla1.campo3" & filtro ' & ";"

Si en cambio sustituyo valor1 por una constante cualquiera, el error se corrige.

Aparte de entender porqué se produce este comportamiento, necesito actualizar el valor del campo1 con el valor del campo3 del mismo registro.

¿alguna idea?


Editado por naiki - 27/Febrero/2018 a las 16:49
Arriba
JuanW Ver desplegable
Habitual
Habitual
Avatar

Unido: 12/Mayo/2005
Localización: España
Estado: Sin conexión
Puntos: 147
Opciones de entrada Opciones de entrada   Gracias (0) Gracias(0)   Cita JuanW Cita  ResponderRespuesta Enlace directo a este mensaje Enviado: 01/Marzo/2018 a las 11:25
De momento tienes una errata en la sentencia:
sql1 = "UPDATE tabla1 SET campo1='valor1'" & filtro ' & ";"
la comilla simple sobra o te hace falta otra.

Por otro lado, si dices que sustituyes valor1 por una constante, y eso no me cuadra, ya que lo que tienes en la sentencia es precisamente una constante de texto.
Para que fuese variable deberias poner en vez de "valor1" por: '" & valor1 & "'

Saludos
Arriba
naiki Ver desplegable
Nuevo
Nuevo
Avatar

Unido: 26/Febrero/2018
Localización: Madrid
Estado: Sin conexión
Puntos: 7
Opciones de entrada Opciones de entrada   Gracias (0) Gracias(0)   Cita naiki Cita  ResponderRespuesta Enlace directo a este mensaje Enviado: 01/Marzo/2018 a las 21:50
Cierto, creo que me expliqué mal. Me da error de otro usuario intentando acceder a los datos al mismo tiempo cuando la sentencia es

sql1 = "UPDATE tabla1 SET tabla1.campo1=tabla1.campo3" & filtro & ";"

Si en cambio asigno al campo1 una constante, es decir, algo así:

sql1 = "UPDATE tabla1 SET campo1='valor1'" & filtro & ";"

funciona sin ningún problema. Y no acabo de entender por qué.

El tema de la comilla simple que sobraba era un simple error de transcripción.

Gracias por tu respuesta.
Arriba
 Responder Responder
  Compartir tema   

Ir al foro Permisos de foro Ver desplegable