FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Temas de Hoy |
|
Herramientas | Buscar en Tema | Desplegado |
|
#1
|
|||
|
|||
Todo empieza aqui, este codigo se ejecuta sin problemas
Código:
procedure TMDOQuery.InternalOpen; begin ActivateConnection(); ActivateTransaction; QSelect.GenerateParamNames := FGenerateParamNames; SetPrepared(True); if DataSource <> nil then SetParamsFromCursor; SetParams; inherited InternalOpen; end; Código:
procedure TMDOCustomDataSet.InternalOpen; var SetCursor: Boolean; function RecordDataLength(n: Integer): Long; begin result := SizeOf(TRecordData) + ((n - 1) * SizeOf(TFieldData)); end; begin SetCursor := (GetCurrentThreadID = MainThreadID) and (Screen.Cursor = crDefault); if SetCursor then Screen.Cursor := crHourGlass; try ActivateConnection; ActivateTransaction; if FQSelect.SQL.Text = '' then MDOError(mdoeEmptyQuery, [nil]); if not FInternalPrepared then InternalPrepare; if (FQSelect.SQLType in [SQLSelect, SQLSelectForUpdate]) then begin if DefaultFields then CreateFields; BindFields(True); FCurrentRecord := -1; FQSelect.ExecQuery; ............. hay mas codigo, pero nos interesa hasta ExecQuery ........ Código:
procedure TMDOSQL.ExecQuery; var fetch_res: ISC_STATUS; begin CheckClosed; if not Prepared then Prepare; CheckValidStatement; if (FBase.Transaction.AutoCommit) and not (FBase.Transaction.InTransaction) then begin FBase.Transaction.StartTransaction; end; try case FSQLType of SQLSelect, SQLSelectForUpdate: begin Call(isc_dsql_execute2(StatusVector, TRHandle, @FHandle, Database.SQLDialect, FSQLParams.AsXSQLDA, nil), True); AQUI->> Call( isc_dsql_set_cursor_name(StatusVector, @FHandle, PChar(FCursor), 0), True); FOpen := True; FBOF := True; FEOF := False; FRecordCount := 0; if FGoToFirstRecordOnExecute then Next; end; // Removed the code FCursor set name from the TMDOSQL.Create. // This is needed because if you create the MDOSQL dynamically, the name is // not assigned in the create and the cursor is only based on a 'random' // number. And, in some special situation, duplicate cursornames will appear //FCursor := Name + RandomString(8); buffff, atentos a esto: "And, in some special situation, duplicate cursornames will appear" !!!!! Justo lo que me sucede ahora, ya que muchas querys las creo dinamicamente. Ya me gustaria saber cual es la "special situation" a la que se refieren.... Vale, ya tenemos localizado el problema, los creadores de MDO ya lo sabian, veamos como lo resolvieron.... Código:
procedure TMDOSQL.Prepare; var stmt_len: Integer; res_buffer: array[0..7] of Char; type_item: Char; begin if FCursor = '' then !! Parece que NO LO RESOLVIERON !!! FCursor := Name + RandomString(8); !! Utilizan el randomstring(8) igual que en el codigo editado en el constructor !! CheckClosed; FBase.CheckDatabase; FBase.CheckTransaction; if FPrepared then exit; if (FSQL.Text = '') then MDOError(mdoeEmptyQuery, [nil]); if not ParamCheck then ........ continua ...... Estas son las funciones que generan el nombre (numero) del cursor. Código:
function RandomString(iLength: Integer): String; begin result := ''; while Length(result) < iLength do result := result + IntToStr(RandomInteger(0, High(Integer))); if Length(result) > iLength then result := Copy(result, 1, iLength); end; function RandomInteger(iLow, iHigh: Integer): Integer; begin result := Trunc(Random(iHigh - iLow)) + iLow; end; Si no son seguras, se pueden mejorar??? 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. Los componentes MDO son los que se encargan de los cursores, creacion y destruccion, ¿de que modo podriamos dejar los cursores huerfanos en memoria provocando este error??? Espero que este post ayude a alguien que se encuentre en esta misma situacion, creo que he avanzado bastante en localizar el problema, un poco más y descubriremos que sucede realmente. |
#2
|
|||
|
|||
Cita:
Las transacciones de controlan con TZconnection, que es como un TDataBase + TTransaction. Pero, y si quiero tener más de una transaccion?? Hay que asignar un TZConnection por cada transaccion?? Por lo que he leido, las transacciones se pueden gestionar automatica o manualmente. |
#3
|
|||
|
|||
Código:
// Removed the code FCursor set name from the TMDOSQL.Create. // This is needed because if you create the MDOSQL dynamically, the name is // not assigned in the create and the cursor is only based on a 'random' // number. And, in some special situation, duplicate cursornames will appear //FCursor := Name + RandomString(8); yo de ti no perderia mas el tiempo con estos componentes. Ahora bien, si aun los quieres usar, puedes probar de, en el create del componente, asignar el nombre del cursor de una manera que a ti te convenga :ej, numero de componentes MDOSQL en la aplicacion o con el GetNamePath, asignando el nombre a cada MDOSQL que crees dinamicamente, o bien haciendo overload del create con un parametro de cursor. |
#4
|
|||
|
|||
Efectivamente, es una chapuza, si al menos hubieran dicho cuales son las condiciones especiales se podria tratar de evitarlas.
Parece que tendre que cambiar de componentes, pero mientras tanto, quisiera resolver esto y ganar un poco de tiempo. Afortunadamente, solo un cliente tiene esas condiciones especiales. No me atrevo a meterle mano al codigo de MDO, pero esta claro que de alguna manera debo modificar el nombre del cursor para hacerlo unico, pero no se como hacerlo. Cita:
GetNamePath parece mejor opcion. Esto funcionaria??: FCursor := self.getnamepath + RandomString(8); No es que no quiera probarlo yo mismo, es que me es muy dificil reproducir el error, en mis equipos no pasa. El overload, pues no tengo ni idea de como quedaria, en este punto necesitaria un ejemplo. Última edición por Sick boy fecha: 13-12-2008 a las 15:14:51. |
#5
|
||||
|
||||
Yo me reservo el derecho de criticar.
Para mí, una gente que trata directamente con la API de un SGBBDD y que dan al programador una interfaz al estilo de Interbase, ya se merecen mi respeto, si además lo hacen Open Source, un aplauso para ellos. Y ya ni hablar del elegante diseño de clases, jerarquías, calidad del código, etc. Existen componentes de pago (nada baratos) que sólo ver el código fuente se les debería caer la cara de vergüenza, al menos ese fallo, conceptualmente, no tiene mucha importancia (para Sick boy si lo tendrá porque le está amargando la existencia ). La generación de números aleatorios siempre han tenido ese fallo, pueden repetirse en "determinadas circunstancias". Dicho sea de paso, si la función random hiciera su trabajo bien, los MDO no fallarían . Saludos
__________________
Si usted entendió mi comentario, contácteme y gustosamente, se lo volveré a explicar hasta que no lo entienda, Gracias. |
#6
|
|||
|
|||
Cita:
tambien, ahora que lo pienso, puedes capturar la excepción alla mismo:
Lo que me sigue intrigando personalmente es que tansolo te pase en una unica tabla. Quiza deberias mirar mas profundamente las diferencias entre el diseño de la tabla que da error y el resto. Saludos. Última edición por coso fecha: 13-12-2008 a las 18:57:35. |
#7
|
|||
|
|||
El overload seria algo asi:
etc... Tambien puedes darle un nombre por defecto al componente cuando se crea aunque seria un poco estirar el problema
|
#8
|
|||
|
|||
Cita:
Un poco chapuza dejar el codigo editado y sin corregir, al menos sabian que podia haber un problema. He revisado el codigo de los IBX y tienen el mismo codigo, esta vez sin editar, y no veo que tengan otro mecanismo para solucionarlo. Sobre los numeros aleatorios, ¿Cuales seran las "determinadas circunstancias"? No es que pase solo con una base de datos, es que pasa solo en un PC, yo sigo sin poder reproducir el error en mis ordenadores. Voy a probar una modificacion en la creacion de los numeros aleatorios, y quizas tratar de capturar la excepcion como sugiere coso. El lunes podre probarlo en el cliente y os comento si funciona. Por cierto, las tablas son iguales, no hay ninguna diferencia. Incluso rellene una base de datos nueva y vacia con los datos de la que daba problemas, y sigue igual. |
#9
|
|||
|
|||
...todo un misterio...¿no tendra algo que ver el nombre de la tabla?...bueno, ya nos diras. Saludos y suerte.
|
#10
|
||||||||||
|
||||||||||
¡Hola a todos!
Descargué la biblioteca de componentes Mercury Database Objects —MDO— (la misma versión que está usando Sick Boy, según me comentó), para echar un vistazo con mayor cercanía, específicamente sobre lo que se ha comentado de las unidades MDOSQL.pas y MDOUtils.pas (lo del nombre de cursor aleatorio, vaya), comparando diferencias con las unidades equivalentes nativas IBSQL.pas y IBUtils.pas de los IBX. 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. 2. Los creadores de MDO movieron esa sentencia al método Prepare, como bien lo señalaste, pero en los IBX sí está habilitada en el constructor de TIBSQL, por lo que, en ese caso, el nombre del cursor siempre será solamente lo que devuelva la función RandomString (un número aleatorio de 8 dígitos). Un dato importante para los usuarios de IBX. 3. Esto me hace pensar, y trato de recordar si lo que voy a mencionar es cierto, que en versiones más antiguas de Delphi, al agregar un componente a un formulario o módulo de datos en tiempo de diseño, dicho componente obtenía su nombre predeterminado ("Label1", "IBSQL1") por medio del constructor Create de TComponent. Si alguien tiene Delphi 5 o anterior y algo de tiempo para comprobar ésto definiendo e instalando una clase de componente de prueba que muestre su nombre como última sentencia del constructor, se lo agradecería. 4. 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. Cita:
Cita:
Cita:
Cita:
Cita:
Aun cuando ya no suelo usar este tipo de componentes especializados en un motor (tarde o temprano te enamoras de dbExpress con TClientDataSet ), creo que cambiar de componentes sería algo aventurado en este momento. Cita:
Cita:
Te sugiero emplear la misma función, RandomString, pero con un valor de 1 en lugar de 8, para intentar reproducir las condiciones que generan la excepción. Cita:
Cita:
Como punto y aparte, y a pesar del análisis anterior, yo no descarto que la causa del problema pueda ser otra cosa. Esperemos a ver qué nos trae Sick Boy... Un abrazo sin nombre. Al González. 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. Última edición por Al González fecha: 14-12-2008 a las 09:39:45. |
|
|
Temas Similares | ||||
Tema | Autor | Foro | Respuestas | Último mensaje |
Mensaje de error extraño | Sick boy | Firebird e Interbase | 0 | 12-12-2008 11:22:26 |
Error Extraño | SysAdminGCS | Varios | 1 | 18-08-2007 16:30:49 |
Error Extraño | Esau | SQL | 4 | 17-06-2005 22:44:16 |
error extraño | gilberto_1126 | Varios | 2 | 05-09-2004 01:01:01 |
Error Extraño | Esau | OOP | 5 | 19-11-2003 18:01:32 |
|