Sergio te agradezco por las aclaraciones

Saludos,
Escrito 15 febrero 2011 - 08:02
Escrito 18 febrero 2011 - 06:47
Sí, eso lo pierdo de gestionarlo a través de Firebird, pero con los ClientDatasets de Delphi consigo el mismo resultado con mucha menos carga para el Servidor.
Todos pueden modificar, pero el primero que graba es el que tiene éxito : se inicia otra minitransacción, se actualizan los datos en disco y se cierra la transacción.
Cualquier otro que intente grabar posteriormente esos datos, se va a encontrar con que el ClientDataset detectará que los datos en disco no son los mismos que él leyo y copió en memoria, y en lugar de actualizar los datos lanzará una excepción de Conflicto de Actualización (donde puedes mostrar una pantalla de Conciliación, mostrando la versión original del campo, tus cambios, la nueva versión en la base de datos de esos campos y escoger los que quieres que queden definitivamente).
Esto se controla mediante la propiedad UpdateMode del Provider del ClientDataset. Con upWhereAll todos los campos del ClientDataset tienen que tener aún el mismo valor, con upWhereChanged vas a poder grabar el ClientDataset si solo los campos que estás modificando mantienen el valor original, y con upWhereKeyOnly indicas que no te quieres preocupar por eso y que quieres grabar siempre los datos (independientemente de que otro haya hecho cambios mientras tú los editabas).
Escrito 18 febrero 2011 - 08:14
Marc, esto me interesa y bastante, ya que actualmente usamos FreeIB porque al ser componentes directos nos permiten jugar con la concurrencia, tipos de transaccion, etc., pero si hay otra forma mejor de hacerlo, me gustaria probarlo (estos componenetes que usamos huelen a muerto hace tiempo, los tenemos "parcheados" por nosotros para el dialect 3 y tienen un 3 o 4 fallitos molestos que no podemos/sabemos corregir y nos limitan bastante).
La estructura que tu usas, por lo que entiendo, es como si fuese un programa multi capa, pero con las dos capas en la misma applicacion: Tienes los ClientDataSet que son los que se muestran al usuario, pero conectan con un dbExpress que vive en la misma aplicacion, que son los que hacen esas mini transacciones.
Esto nos quitaria de encima los molestos FreeIB y nos permitiria incluso conectar con otros tipos de gestores de bases de datos tipo SQL Server.
Preguntas que tengo para ti:
1) Usais dos capas "reales" o teneis todo en la misma aplicacion?
2) dbExpress que tal van con FireBird? (si se pierden posibilidades respecto de una conexion "directa" tipo FreeIB, FIBPlus, etc)
3) Hasta que punto este enfoque es independiente de FireBird (tenemos un posible cliente que si no es con SQL server no quiere, el responsable de IT trabajaba antes en MS en los USA y los añora mucho?
4) Como es la estructura concreta de la aplicacion: En cada form (ficha, dbgrid, o lo que sea) supongo que teneis un ClientDataSet, pero ¿Cada ClientDataSet contra que conecta?
En su dia miramos los dbExpress pero no nos gustaron por un tema que no se si ya estara resuelto: Si haces un select * from tabla con FreeIB, y en tu grid se muestran 20 lineas, solo se "trae" del servidor FireBird las primeras 20 lineas, es decir, que las FreeIB se ocupan de pedirle al serivodr solo los record que relamente se muestran, mientras que los dbExpress se traen todos los record al ejecutarse.
Si los dbExpress no tienen ocion de traerse solos los records conforme se utilizan, tendriamos que plantearnos controlar eso desde programa, porque ahora usamos con mucha alegria select que se traen miles de record complejos SIN agobiar excesivamente al servidor ni quedarnos sin meoria (bueno, si pides un listado de esos datos, te quedas sin memoria, eso si).
Escrito 23 febrero 2011 - 10:15
Escrito 23 febrero 2011 - 12:21
Lo que creo que no calibré al preguntarte es que tu debes usar la version enterprise/architect, y aqui en principio solemos tirar por la profesional, con lo que creo -no lo he comprobado- que no trae esos componentes, asi que o nos costara mas dinero migrar a delphi "moderno", o usaremos IBObjects o UIB, las otras dos opciones que barajamos (UIB es perfecto para nosotros, pero ya veremos al cambiar unos por otros donde empieza a quejarse).
Escrito 23 junio 2011 - 06:32
Escrito 23 junio 2011 - 07:53
Escrito 23 junio 2011 - 10:33
Escrito 23 junio 2011 - 10:42
Hola de nuevo Marc,
Estamos retomando este tema a ver si llegamos a ser "compatibles con D2007 y UniGUI", y nos surge unas pocas cuestiones respecto de esto del dbExpress y los ClientDataSet, a ver si puedes arrojarnos algo de luz:
1) Si vas a dar de alta una factura, es decir, la cabecera de factura, mas sus n lineas de factura, mas su asiento contable, mas su asiento de IVA, mas lo que sea que toque: Puedes agrupar todo esto en una transaccion "clasica" y que o todo se grabe o nada?
2) El ClientDataSet va bien para dbGrids o para fichas estandard, pero si quieres una consulta con parametros, con un ExecuteBlock, y demas cosas "avanzadas" ¿Como se hace con este esquema? Suponogo que depende del DataSet de donde partas, perome refiero a usando dbExpress (igual no se puede y usas otros sistemas alternativos para estas cosas).
Gracias de antemano.
Escrito 23 junio 2011 - 11:16
Yo pensaba que si abrías manualmente una transacción, el ApplyUpdatase del ClientDataset la detectaba y se ejecutaba dentro de esa transacción (con lo que puedes agrupar varias grabaciones), y tengo escrito todo el código así.
Pero haciendo unas pruebas, el otro día, me parece que esto no acaba de funcionar exactamente así. Por lo que no he acabado de investigarlo, pero seguro que hay una forma para indicarle al ClientDataset que haga sus grabaciones sobre una transacción explícita.
Escrito 23 junio 2011 - 12:05
El amigo Wilson explica mas arriba que el DataSetProvider tiene una transaccion para estos usos, mas no te puedo decir, solo que siento que hayas descubirto que las transacciones te son infeles, pero mejor asi que se de cuenta tu cliente y te saque los colores!
private FTransaccion: TDbXTransaction; //.... // Procedimientos suceptibles de fallas procedure TDMSolicitudes.SolicitudesBeforeUpdateRecord (Sender: TObject; SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind; var Applied: Boolean); begin if UpdateKind = ukInsert then if SourceDS = qSolicitudes then DeltaDS.FieldByName('NUMERO').NewValue := GetNumeroSoli else DeltaDS.FieldByName('ID_DETALLE').NewValue := GetIdn; end; procedure TDMSolicitudes.SolicitudesAfterUpdateRecord (Sender: TObject; SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind); var S, T, ts: string; begin if SourceDS = qSolicitudes then begin S := 'ID_SOLICITUD'; T := 'SOLICITUDES'; ts := 'SOLICITUDES'; Controlar(T, ts, S, DeltaDS, UpdateKind, ConSol); end; if SourceDS = qDetSolicitud then begin S := 'ID_DETALLE'; T := 'DETALLES SOLICITUDES'; ts := 'DETALLES_SOLICITUDES'; Controlar(T, ts, S, DeltaDS, UpdateKind, ConSol); end; end; //manejo de la transacción procedure TDMSolicitudes.SolicitudesBeforeApplyUpdates (Sender: TObject; var OwnerData: OleVariant); begin FTransaccion := Conexion.BeginTransaction(TDBXIsolations.ReadCommitted); end; procedure TDMSolicitudes.SolicitudesAfterApplyUpdates (Sender: TObject; var OwnerData: OleVariant); begin if Conexion.InTransaction then Conexion.CommitFreeAndNil(FTransaccion); end; procedure TDMSolicitudes.SolicitudesUpdateError(Sender: TObject; DataSet: TCustomClientDataSet; E: EUpdateError; UpdateKind: TUpdateKind; var Response: TResolverResponse); begin if Conexion.InTransaction then Conexion.RollbackFreeAndNil(FTransaccion); end;
Escrito 23 junio 2011 - 12:37
Escrito 23 junio 2011 - 01:44
Hola Wilson.
En tu código, ¿ como aseguras que las actualizaciones del ClientDataset en el ApplyUpdates se van a ejecutar sobre la transacción FTransaccion, que has abierto en el BeforeApplyUpdates ?.
En ClientDatasets + dbExpress, si hay una transacción abierta en el SQLConnection, las actualizaciones del ClientDataset se ejecutan sobre ella, ¿ verdad ?. Por eso si quieres englobar la actualación de varios ClientDatasets en una misma transacción, solo tienes que abrirla manualmente antes de aplicar los ApplyUpdates (aparte de que como la transacción la controlas mediante tu código, en esa misma transacción puedes englobar la ejecución directa de SQLQuerys, o lo que sea que puedas necesitar).
Escrito 27 junio 2011 - 09:52
Escrito 28 junio 2011 - 06:36
Interesante pregunta:
Hace unos 4 o 5 años vi un articulo sobre que capacidad de almacenamiento, tenia Firebird
y esto fue lo que encontre
Windows:
FAT12 has a 32MB file size limit
FAT16 has a 2GB file size limit (Windows NT 3 or newer)
FAT32 has a 2GB file size limit
FAT32 has a 4GB file size limit (Windows NT5 / 2000 and newer)
NTFS has a 4GB file size limit (Windows NT)
NTFS has a 16EiB file size limit (Windows NT5 / 2000 and newer)
Linux:
EXT2/EXT3 (with 4kB blocksize) has a 2TB file size limit
EXT2/EXT3 (with 8kB blocksize) has a 64TB file size limit
ReiserFS 3.6 has a 1EiB file size limit
XFS has a 8EiB file size limit
JFS (with 512b blocksize) has a 8EiB file size limit
JFS (with 4kB blocksize) has a 8EiB file size limit
esto lo tome de un articulo
http://www.intitec.c...os-Firebird.pdf
claro esta que esto ha cambiado los sistemas FAT desaparecieron
Saludos