Ver Mensaje Individual
  #25  
Antiguo 14-12-2008
Sick boy Sick boy is offline
Miembro
 
Registrado: may 2003
Ubicación: Cantabria
Posts: 245
Reputación: 21
Sick boy Va por buen camino
Ole, no se por donde empezar.

Cita:
1. El nombre de un componente (propiedad Name) es una cadena vacía durante su construcción. A menos que el constructor realice, directa o indirectamente, una asignación de valor a la propiedad Name, no tiene sentido usarla como parte de una expresión dentro del constructor.
Ayer ya me di cuenta (le puse un showmessage al crear el cursor) de que la propiedad Fname no tiene ningun valor. Salvo que haya otro punto donde se creen los cursores, Fname es vacio tanto si creas el objeto en diseño o en ejecucion. Por lo tanto, todos los cursores son numeros de 8 digitos.

Efectivamente, el prefijo Fname ayudaria mucho a crear cursores unicos.

Cita:
Los creadores de MDO movieron la sentencia al método Prepare, con el argumento de "if you create the MDOSQL dynamically, the name is not assigned in the create and the cursor is only based on a 'random' number". Es claro que se dieron cuenta de lo mismo que comenté anteriormente (desde X versión de Delphi, o quizá desde siempre, la propiedad Name no tiene valor durante la ejecución del constructor). Pero asumen, o dan por recomendado, que debe asignarse un valor a la propiedad Name del objeto antes de ejecutar la consulta para que el nombre del cursor quede más rico y sea menos probable que se repita, lo cual es sencillo si el componente es agregado en tiempo de diseño o lo instanciamos nosotros mismos y enseguida le damos valor a Name. Sin embargo, la clase común TMDOCustomDataSet, al igual que sucede en los IBX, crea varias instancias internas de estos objetos SQL sin darles valor a su propiedad Name (a no ser que lo haga en algún punto del código que no logro ver). Así pues, con el nombre del cursor (FCursor) generado en el constructor Create o en el método Prepare, éste siempre será un número de 8 dígitos, a menos que se trate de un componente TMDOSQL que nosotros mismos hayamos preparado.
Bueno, me dices que name deberia tener un valor en componentes creados en tiempo de diseño, pero estoy casi seguro de que no es asi, los cursores siempre son 8 digitos. Voy a ver si consigo darle valor a Name, creo que seria una buena solucion.

He seguido investigando en el codigo MDO, y veo que TMDOSQL no tienen por ninguna parte la propiedad Fname, mientras que la clase TMDOXSQLVar si que la tiene. Por lo que veo es la unica clase con esa propiedad.

Por ahora, no veo la forma de darle valor a Name, creo que esto mejoraria la situacion.

Acabo de pasar el randomString(1), es decir, los cursores son un numero de un digito, name sigue siendo nulo. Como era de esperar la aplicacion arranca con problemas, pero ya puedo reproducir el error facilmente.

Cita:
Cita:
Empezado por Sick boy Ver Mensaje
...Por otro lado, si el problema no es por la generacion del numero de cursor, entonces es que un cursor se queda "pillado", pero no se como puede ser posible...
Eso necesitaría de otra línea de investigación. Pero dinos una cosa: en las máquinas donde falla, ¿cuántas veces por día u hora tu programa realiza una consulta Select sobre la base de datos? Una cifra estimada.
La pregunta es ¿cuantas veces abre el mismo Select? o ¿cuantos select/insert/... se realizan??
En este caso, el cliente realiza un uso bajo de la aplicacion, hay clientes que le superan por mucho.
Aproximado, no se, quizas 500 sentencias por hora. Algunas de las operaciones habituales requieren unos 6 cursores.

Cita:
P.D. Algo más: ¿alguien conoce el ámbito que tienen los nombres de cursores? ¿Es por conexión (programa), por máquina cliente, globales para todos los clientes...? Pienso que deberían ser por conexión/transacción, pero quisiera confirmarlo.
No estoy seguro, pero ahora que tengo cursores de un digito, te puedo indicar que el cursor 1 puede habrirse 3 veces seguidas sin problemas, y quizas la cuarta de el error, asi que debe ser a nivel de transaccion, o me daria el error al salir la segunda vez.

Acabo de descubrir algo interesante.
Le he puesto transaction.name y sql.text al showmessage que me indicaba cuando un cursor nuevo es creado. Tambien he puesto un showmessage para ver los cursores que no son nuevos. Los cursores son de 1 digito.
Los cursores reutilizados funcionan bien.
Los cursores nuevos, nunca tienen nombre, y parece que el ambito es la transaccion, ya que si haces un comit, la proxima vez que se abre el cursor aparece como NUEVO y le asigna un nuevo numero sin problemas. Diferentes transacciones y mismos numeros hasta ahora todo bien.

La sorpresa es que los select internos tipo "Select F.RDB$COMPUTED_BLR, F.RDB$DEFAULT_VALUE ....." no llevan asignado un nombre de transaccion.
Cuando comienzan a abrirse estos cursores, en pocas sentencias se produce el error, por ejemplo, detecta que el cursor 1 ya esta declarado y salta la excepcion. Cada vez que vuelva a aparecer ese cursor 1 en la transaccion "sin nombre" saltará el error.
He puesto un timer que repite una sentencia SQL simple, el select mio se ejecuta bien en la transaccion que tiene asignada. Al ejecutar la sentencia interna que te devuelve los valores por defecto, campos calculados, .... el cursor asignado en los 10 ultimos select ha sido el 1 (poco aleatorio, pero bueno) y cada vez que sale el 1 da error en ese select, no en el mio.
Si aleatoriamente sale un numero distinto del 1 la sentencia funciona correctamente.

Si cierras la aplicacion y la vuelves a abrir comienza todo, por lo que creo que el ambito del cursor es a nivel de transaccion/conexion.
Responder Con Cita