Visual Basic.NET - Problemas con los bloqueos SQL

 
Vista:

Problemas con los bloqueos SQL

Publicado por albert (4 intervenciones) el 27/11/2007 17:58:45
Saludos amigos,
tengo un GRAN problema con un programa informático hecho en VB .NET, y con el SGBD SQL Server 2000. El problema está relacionado con los bloqueos. El programa es cuestión sirve para gestionar empresas de obras y servicios. El programa está distribuido es decir, varios usuarios tienen acceso a la vez a los datos de la base de datos.
El programa funciona perfectamente excepto para un caso, que es el siguiente:

Un usuario conectado a la BD accede a un formulario de envío de material a obra, en dicho formulario se introducen datos, se introducen materiales a enviar a obra. Cuando se acepta el detalle del formulario se registra en la base de datos unos movimientos de stock de material y se accede a la tabla Contadores donde cada registro tiene Codigo_Contador, Descripcion y Valor del contador, para consultar el Codigo_Contador que le corresponde a cada movimiento de stock. Este usuario sin ACEPTAR el formulario para hacer el COMMIT, se espera y deja abierto el formulario (por cualquier motivo).

Paralelamente otro usuario accede al programa y a la BD, accede a hacer un Albarán de compra de material para enviar al almacén de la empresa. Este formulario tiene unas lineas de detalle que son los materiales que se enviarán al almacen. Cada linea de detalle registará un movimiento de stock hacia el almacén de dicho material. Cuando le damos a ACEPTAR el formulario para acabar el albarán SE NOS QUEDA COLGADO!!! Resulta que se cuelga hasta que el 1er usuario acepta o cancela su formulario.

Hemos estado investigando, ya que es un programa bastante complejo, con muchas horas de trabajo (2 años), y la persona que realizó el tema de los bloqueos ya no está. Hemos detectado que el problema es de bloqueos, todas las sentencias INSERT tienen un WITH (NOLOCK) para mejorar eficiencia pero quizá sea el culpable de este bloqueo.
Hemos detectado tb que esto sucede pq aun no se ha hecho el COMMIT de la transaccion que bloquea el registro de la tabla Contadores descrita anteriormente, ya que ambos usuarios acceden al mismo registro para consultar e incrementar posteriormente el contador Valor_Contador del registro.

Os pido ayuda ya que he probado diversas cosas pero sigue quedandose colgado!!!
A quien me ayude le prometo que le envio un regalo!!! Ropa interior Calvin Klein!!
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
sin imagen de perfil

RE:Problemas con los bloqueos SQL

Publicado por P. J. (706 intervenciones) el 27/11/2007 19:43:07
Un regalo?? :D

Tu sistema trabaja con datos CONECTADOS???, o sea la conexion nunca se cierra desde que entra el usuario?

Yo controlo las transacciones desde el .Net, de esta forma

Dim oSqlConn As New SqlConnection(strCadena)
oSqlConn.Open()
Dim oSqlTransaction As SqlTransaction = oSqlConn.BeginTransaction()

Pues con esto ahora mi cadena de conexion esta en oSqlConn, ya despues la uso en todos los Execute, y al final pongo

oSqlTransaction.Commit()
Catch ex As Exception
oSqlTransaction.Rollback()
Finally
If Not oSqlConn Is Nothing Then oSqlConn.Dispose()
End Try

Claro, falta la apertura del try, pero en conclusion de esta manera si controla bien las transacciones. Si esta desde el SQL, no bloquees, prueba con:

BEGIN TRANSACTION
...
...
-- INSERT INTO....

COMMIT TRANSACTION

Nada mas.
Salu2
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

Error

Publicado por P. J. (706 intervenciones) el 27/11/2007 20:08:01
Dim oSqlTransaction As SqlTransaction = oSqlConn.BeginTransaction()

Pues con esto ahora mi cadena de conexion esta en oSqlTransaction , ya despues la uso en todos los Execute, y al final pongo

La cadena de conexion pasa a oSqlTransaction, jeje.

Suerte!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Problemas con los bloqueos SQL

Publicado por Albert (4 intervenciones) el 28/11/2007 11:45:25
Gracias por tu ayuda,
la manera de controlar las transacciones en nuestro programa es mediante el tipo ADO haciendo iniciando transaccion y posteriormente depende de si aceptamos o cancelamos la operacion con commit o cancel. En general no tengo problemas con los bloqueos sólo en el caso concreto que he comentado, debido a que un usuario abre transaccion con un registro de la tabla Contadores, sin hacer el aceptar (commit) otro usuario accede al mismo registro coge el valor lo usa, lo incrementa y cuando quiere guardarlo entonces el programa se bloquea ya que el primer usuario debe de hacer el commit. He probado varias cosas y no funciona, no es una cosa trivial, ya que el programa tiene mucha envergadura, y no puedo modificar en general el funcionamiento de los bloqueos, ya que me llevaría algunas semanas y más de un disgusto. Creo que en todo el programa no hay ningun caso como este, si soluciono este problema estaré más que satisfecho, y asi puedo revisar tranquilamente todo el programa en busca de posibles nuevos bloqueos.
En fin, ya sé que no pongo mucha información, es que sinceramente no sé qué poner para que me podais ayudar. El tema de la ropa interior es totalmente cierto, aparte de programador tengo unos "trapis" con ropa interior Calvin Klein exportada de China y la vendo a conocidos. Si me ayudas te regalo alguna prenda, y si no te lo agradezco y si quieres puedes escribirme para solicitar el catálogo de ropa interior ;) ([email protected])
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

RE:Problemas con los bloqueos SQL

Publicado por P. J. (706 intervenciones) el 28/11/2007 15:20:44
JAAJAAJA, que buena con la publicidad :D

En fin, me gustaria ayudarte pero la informacion es poca, lo que yo hago para controlar transacciones es como te deje en mi primer msj.

Yo participo de un proyecto ( bastante GRANDE ), y en la capa del DAL, donde se manejan la vinculacion con la BD, alli recien inicio las transacciones, por eso no se bloquean las tablas.

Tu tabla contadores, seguro guarda los correlativos para algun documento, yo tengo algo similar y normal funciona, pero controlando como te menciones antes.

Por ejem: Yo tengo un documento, alli le muestro al usuario el numero del documento (que lo busco en una tabla), y cuando guarda, recien inicio la transaccion, vuelvo a buscar el numero en la tabla (ya que puede que otro usuario haya registrado lo mismo), inserto los datos y doy COMMIT, si hubo algun fallo ROLLBACK.

Pues esto de las transacciones, en ocaciones es FASTIDIOSO, mas por los usuarios finales que piden CADA COSA!

Ojala tengas suerte, saludos.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Problemas con los bloqueos SQL

Publicado por Albert (4 intervenciones) el 28/11/2007 16:09:56
Pero donde crees tú que debería poner lo que me comentas?

Yo ahora lo tengo así:

cuando el usuario accede al formulario dentro del código se llama al método "IniciarTransaccion" que contiene el siguiente codigo:
Public Sub IniciarTransaccion()
On Error Resume Next
If NivelTransaccion = 0 Then
ADNDB.BeginTrans()
End If
NivelTransaccion = NivelTransaccion + 1
FormularioPrincipal.BarPie.Panels(1).Text = "TRANSACCIÓN"
End Sub

Entonces el usuario empieza a rellenar y consultar campos del formulario. De repente otro usuario accede al programa entra en el formulario de compras de material para enviarlas al almcén y dentro de su código tiene otro: "IniciarTransaccion". En este instante nadie a hecho el Commit y entonces se me produce el bloqueo al acceder al registro de la tabla Contadores, y no se desbloquea hasta que el 1er usuario ha aceptado el formulario y ha llamado al método "ConfirmarTransaccion":
Public Sub ConfirmarTransaccion()
On Error Resume Next
If NivelTransaccion = 1 Then
ADNDB.CommitTrans()
FormularioPrincipal.BarPie.Panels(1).Text = ""
NivelTransaccion = NivelTransaccion - 1
ElseIf NivelTransaccion > 1 Then
NivelTransaccion = NivelTransaccion - 1
End If
End Sub

O bien al mismo CancelarTransaccion. En este instante se me desbloquea y el 2do usuario puede guardar sus datos. Alguna sugerencia de nuevo?
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

RE:Problemas con los bloqueos SQL

Publicado por P. J. (706 intervenciones) el 28/11/2007 17:53:08
Creo que estamos en lenguajes distintos, yo uso el vb.Net, tu el vb 6.0 ¿no?

Pero igual, la transacción tu la inicias al MOSTRAR EL FORMULARIO!?, pues esta mal, ya que tu no sabes cuanto tiempo va a permanecer el usuario viendo la pantalla.

Lo que hago, es en el BOTON GUARDAR, antes de iniciar las inserciones, inicio transacción, y como son milisegundos, pues no hay problema,

Algunos lo controlan por el lado del SQL, ya que este te pone en espera, pero depende de la programación y tamaño del proyecto.

Porque no haces:

Private sub cmdGrabar_click()
ADNDB.BeginTrans()
On error goto cn
ADNDB.execute(“nsert into …. “)
Cn:
If err then ADNDB.RollbackTrans()
ADNDB.CommitTrans()
End sub

Pues no recuerdo exactamente el vb 6.0, pero asi se insertaba un registro, y controlando la transacción.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Problemas con los bloqueos SQL

Publicado por Albert (4 intervenciones) el 29/11/2007 10:19:28
Saludos y gracias de nuevo,
trabajo con VB .NET igual que tu!!
La opción de añadir el boton GUARDAR de momento no la planteo pq tiene un impacto ENORME en el programa. Actualmente tengo 2 botones, ACEPTAR (hace el commit) y CANCELAR (rollback), y efectivamente el esquema del código es asi:
*********************
Abrimos_Formulario;
IniciarTransaccion();
....
realizamos_acciones_con_el_formulario que pueden ser consultas de datos, modificaciones o eliminaciones o inserciones.
....
Una vez el usuario ha acabado debe de escoger si ACEPTAR o CANCELAR lo que ha hecho (commit o rollback).
************************
Efectivamente tenemos el principal problema que NO SABEMOS cuanto rato estará el usuario con el formulario abierto. Cómo lo solucionamos?

Las acciones que realiza el formulario normalmente son las mismas, o consultas o modificaciones/inserciones de datos entonces abrimos Colecciones o RecordSet con los datos haciendo OPEN, por ejemplo:
DatosEmpresa.Open("SELECT * FROM Empresa") .....

Con el Open obtenemos los datos y los ponemos en el RecordSet DatosEmpresa, posteriormente podemos consultar o añadir nuevos registros:
Consultar ejemplo: DatosEmpresa.GetField("Nombre_Empresa");
Modificar dato ejemplo: DatosEmpresa.SetField("Nombre_Empresa");

Entiendo tus comentarios y estoy viendo los problemas que tengo en mi codigo al usar el begin al principio de un formulario y no cuando toca. Pero la verdadera pregunta es: Cuando debería de poner el Begin...Commit/Rollback? Justo antes de hacer un INSERT? o Bien siempre que consultara datos a la base de datos. Ten en cuenta la estructura que te he explicado anteriormente con los RecordSet o Colecciones.
Muchas gracias amigo, te estás mereciendo el premio que te dije ;)
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

RE:Problemas con los bloqueos SQL

Publicado por P. J. (706 intervenciones) el 29/11/2007 15:22:44
Ahhhh, totalmente DISTINTO a como yo trabajo, pero

Programas en .NET y usas CONTROLADORES DE ERRORES del VB 6.0, ¿RECORDSET?!!!

Bueno cada programador con su estilo. XD

Yo uso solo BEGIN TRANSACTION solo cuando INSERTO, ACTUALIZO, ELIMINO, ... para hacer consultas, o vistas pues no es necesario ya que solo LISTARAS.

En tu caso creo ¿? que deberias poner el BEGIN TRANSACTION en tu boton Aceptar, pero ¿como insertas un registro nuevo?, verdad que es un esquema de trabajo distinto, en conclusion adecualo asi:

.................
................
begin transaction
insert into... Ó update... Ó delete
IF error THEN rollback
commit

Como te comente en todos mis mensajes :D, yo lo hago asi, y eso que cuando uso procesos amplios estos insertan, eliminan y actualizan en otras tablas.

Que tengas suerte Albert.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar