manera preferible escribir la base de datos de Delphi aplicaciones con transacciones y componentes para datos

StackOverflow https://stackoverflow.com/questions/3833432

Pregunta

¿Cuál es la forma preferible de escribir aplicaciones de bases de datos de Delphi que utilizan las transacciones y también componentes para datos?

Tengo que escribir una aplicación cliente que acceden a las tablas InnoDB, y hacer algo de maestro-detalle tipo de cosas dentro de las transacciones. Después de hacer algunas investigaciones sobre las transacciones (desde el punto de vista general), entonces yo humildemente llegar a una conclusión que no reconocimiento de datos y componentes de SQL codificado a mano sería el "perfecto" de las transacciones; Pero los componentes para datos no serían. no parece que hacer para ser uno para el otro.

Tengo la necesidad real de las transacciones de uso, pero por el contrario no podría simplemente tirar los componentes para datos de distancia, ya que las cosas simplificar enormemente.

¿Podría alguien por favor me ilumine? He estado buscando en Google, pero no he encontrado ninguna respuesta útil. Tal vez porque mi Inglés no es lo suficientemente bueno que mis palabras clave son limitados.

Por cierto, estoy usando Delphi 7 y en la actualidad evaluando UniDAC como la biblioteca de acceso a datos.

Gracias.

Editar

Ejemplo para describir un aspecto de mi pregunta:

Imagine un formulario con 2 DBGrids en él. La primera red es MasterGrid y por encima de ella son los siguientes botones: añadir, editar y borrar. La segunda rejilla es DetailGrid. Si el usuario haga clic en Agregar, a continuación, ir de esta manera:

  • Connection.StartTransaction
  • Master.Append continuación Master.Post continuación Master.Edit (por lo que el conjunto de datos principal tiene la clave principal incremento automático, y es editable ahora)
  • Mostrar la forma de editar de forma modal, en el que el usuario rellene los registros maestros, y también añadir algunos registros de detalles de uso de otra forma.
  • Si el usuario haga clic en Aceptar, la aplicación haría Master.Post y Connection.commit. Si el usuario hace clic en Cancelar, a continuación, la aplicación haría Connection.rollback.

Yo sé que las transacciones deben ser lo más corto posible, pero se puede ver por encima de que la transacción es tan corta como la velocidad del usuario rellenando el formulario.

Si estuviera usando componentes que no sean compatibles con datos, que haría que la costumbre de inserción LSQ base de datos del usuario, a continuación, ejecutar el código SQL entre StartTransaction y comprometerse. Por lo que puedo lograr transacción muy corto.

EDIT 2

Gracias a todos ustedes por su amable participación. Tomo la respuesta de vcldeveloper porque es la solución más cercana a mi necesidad actual.

¿Fue útil?

Solución

Otros menciona el uso de una combinación de DataSetProvider y ClientDataset tener una actualización por lotes, pero en el caso de la utilización de componentes de ADO o UniDAC, que no necesita la capa adicional de DataSetProvider + ClientDataset, debido a que ambas actualizaciones por lotes de apoyo ADO y UniDAC.

ADO , lo que debe hacer es ajustar LockType de su conjunto de datos a ltBatchOptimistic . Para UniDAC usted debe ajustar CacheUpdate propiedad a True .

Este cambio hace que el conjunto de datos para almacenar en caché todos los cambios que realice en su conjunto de registros en memoria, y les alltogether enviar a la base de datos sólo cuando se llama a método UpdateBatch (ADO) o ApplyUpdates (UniDAC).

Ahora lo que debe hacer es dejar que su usuario insertar / editar un registro en la base de datos principal y lo graba él / ella quiere en los detalles conjunto de datos utilizando cualquier componentes conscientes de que te gusta. Todos los cambios se almacenan en caché. Cuando se realiza el usuario, puede iniciar una nueva transacción, y la primera UpdateBatch llamada (o ApplyUpdate en caso de UniDAC) para el conjunto de datos principal, y luego para la información de datos, y si todo va bien, confirmar la transacción.

Esto hará que sus transacciones a corto sin necesidad de la capa adicional de ClientDataset.

Regards

Otros consejos

entiendo su pregunta, creo. Al abrir un TADODataSet con, por ejemplo 10 filas de datos a ser editados en un formulario, con los componentes de datos, hay situaciones en las que usted quiere almacenar todos los cambios realizados en todas las 10 filas (y posiblemente deleciones e inserciones) y comprometerse como un lote . No se puede abrir la transacción en el primer cambio, porque eso sería bloquear a otros usuarios que cambian los mismos datos. Las transacciones deben ser lo más corto posible.

Lo que hago en el escenario esbozado es utilizar los siguientes componentes en una cadena:

TADOConnection >> >> TADODataSet TDataSetProvider >> >> TClientDataSet TDataSource >> TDBEdits etc.

Ahora todos los cambios se almacenan en caché en TClientDataSet y se le puede llamar de ApplyUpdates método para publicar todos los cambios en una transacción rápida. Cuenta que también es posible utilizar varios TADODataSets y múltiples TClientDataSets para un maestro-detalle estructura (-detail-etc) con conjuntos de datos anidados. Todos los cambios maestro-detalle también se pueden almacenar en caché y se aplican en un lote en una transacción. Consulte la ayuda y los recursos en otros lugares para todos los detalles acerca de la implementación de este. Al principio no es fácil. Pero si usted lo imaginó es toneladas fáciles y ofertas de posibilidades. (Edición fuera de línea, el examen de los cambios antes de aplicarlos, etc.)

Para evitar la necesidad de realizar grandes transacciones que uso DataSetProviders y ClientDatasets (incluso a nivel local).

Considere el uso de esto como una especie de caché y le da lo mejor de ambos mundos. Puede utilizar los controles de reconocimiento de datos para simplificar las cosas mientras se trabaja en la interfaz de usuario. las acciones del usuario a través de los conjuntos de datos se "registran" por los ClientDataSets (tipo de caché de base de datos).

Cuando el usuario está listo para Guardar los cambios en la base de datos (por ejemplo, los datos de la factura es todo en su lugar), se llama a la método ApplyUpdates para el conjunto de datos (s).

En el caso más sencillo, en el que todos los conjuntos de datos están en una relación maestro-detalle (anidado por el proveedor), el proveedor se inicia y se compromete / reversiones de la transacción por sí mismo, por lo que está en una situación de todo o nada automáticamente.

Si usted tiene relaciones más complejas, puede llamar a StartTransaction antes de iniciar la aplicación de actualizaciones para cada conjuntos ClientDataSet involucradas, y al colgar confirmar o deshacer según sea necesario). La lógica para el proveedor es si la conexión tiene una transacción activa cuando ApplyUpdates se llama, entonces no hace nada con la transacción, pero los cambios simplemente enviar a la base de datos, asumiendo que usted está en control de la transacción.

Hay que leer sobre TClientDataSet y cómo manejar el OnReconcileError y experimentar con la tecnología antes de ponerlo en entornos de producción, pero funciona muy, muy bien para mí.

Mis 2 centavos.

Tiene usted toda la razón en que una escribir transacción debe ser lo más corto posible, y no debería estar vivo todo el tiempo mientras un usuario está llenando el formulario.

La solución general, como ya se ha contestado, es utilizar un nivel intermedio (un ClientDataSet). Pero el verdadero problema con su escenario es que no se puede obtener un valor de incremento automático de la tabla Maestro sin Master.Append y Master.Post, y por lo tanto que iniciar un escribir transacción mucho antes de que se requiere realmente.

Así que si usted no desea utilizar el nivel intermedio y seguir utilizando componentes de datos con corto escritura las transacciones que usted debe pensar de una base de datos que admite la obtención de un valor autoincremented sin ejecutar INSERT (a tabla maestra). El ejemplo es Firebird base de datos, y componentes de acceso a datos FIBPlus para Firebird apoyan plenamente esta función.

Las transacciones debe ser tan corto como necesita . El problema es cómo las diferentes bases de datos asa de bloqueo. Las bases de datos que realizan solamente el nivel de fila de bloqueo y pueden regresar inmediatamente de una cerradura sin tener que esperar mucho menos tienen probabilty a un punto muerto. Por lo general, las inserciones son menos problemáticos (aunque otro usuario no verá comprometida hasta nuevas filas, dependiendo del nivel de aislamiento), actualizaciones y eliminaciones son más problemáticas. Comprometerse con demasiada frecuencia podría ser "malo" también. El almacenamiento en caché los cambios y aplicarlos en una sola operación es otra posibilidad - pero hay que cuestiones de manejar debido a otros usuarios que cambian registros de su parte. No hay una solución "mejor" - todo depende de las necesidades reales. Para algunas aplicaciones (y algunas bases de datos) encargadas del registro bloqueadas, siempre y cuando están cambiando está bien, para otros no. Las actualizaciones por lotes puede ser aceptable en algunos casos y en otros no. Usted tiene que seleccionar el modelo que mejor se adapte a su aplicación y base de datos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top