2010-09-30 17 views
8

¿Cuál es la forma preferible de escribir aplicaciones de bases de datos Delphi usando transacciones y también componentes con capacidad de datos?Forma preferible de escribir aplicaciones de bases de datos Delphi con transacciones y componentes con capacidad de datos

Tengo que escribir una aplicación de cliente que acceda a las tablas de InnoDB, y hacer algunos detalles de tipo de cosas dentro de las transacciones. Después de investigar un poco sobre las transacciones (desde un punto de vista general), humildemente llegué a la conclusión de que los componentes que no tienen en cuenta los datos y el código codificado a mano serían la "combinación perfecta" de las transacciones; Pero los componentes con capacidad de datos no lo serían. No parecen estar hechos el uno para el otro.

Tengo la necesidad real de usar transacciones, pero, por otro lado, no podía tirar los componentes que tienen en cuenta los datos porque simplifican enormemente las cosas.

¿Podría alguien por favor aclararme? He estado buscando en Google, pero no he encontrado ninguna respuesta útil. Tal vez porque mi inglés no es lo suficientemente bueno como para que mis palabras clave sean limitadas.

BTW, estoy usando Delphi 7 y actualmente estoy evaluando a UniDAC como la biblioteca de acceso a datos.

Gracias.

EDITAR

ejemplo para describir un aspecto de mi pregunta: ¿

imaginar un formulario con 2 DBGrids en él. La primera cuadrícula es MasterGrid y encima están estos botones: Agregar, Editar & Eliminar. La segunda grilla es DetailGrid. Si el usuario hace 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)
  • Muestra el formulario de edición de manera modal, en el que el usuario llena los registros maestros, y también agrega algunos registros de detalles usando otro formulario.
  • Si el usuario hace clic en Aceptar, la aplicación haría Master.Post y Connection.Commit. Si el usuario hace clic en Cancelar, entonces la aplicación haría Connection.Rollback.

Sé que las transacciones deben ser lo más breves posible, pero puede ver arriba que la transacción es tan corta como la velocidad del usuario que completa el formulario.

Si estuviera usando componentes que no tengan en cuenta los datos, haría los SQL de inserción personalizados basados ​​en la entrada del usuario, y luego ejecutaría el SQL entre StartTransaction y Commit. Entonces puedo lograr transacciones muy cortas.

EDIT 2

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

+0

Hola, COCIN. Bienvenido a StackOverflow. Tu pregunta no es particularmente clara. ¿Qué problemas tiene al hacer que los controles y las transacciones con datos funcionen entre sí? ¿Puedes editar tu pregunta para proporcionar más detalles? –

+0

¿Por qué dices que los componentes que tienen en cuenta los datos no son buenos para las transacciones? Las transacciones generalmente se manejan en el nivel de sesión de la base de datos; si los comandos DML provienen de SQL hecho a mano o no, eso hace poca diferencia. –

Respuesta

3

Otros mencionaron 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, porque ambos ADO y UniDAC apoyo actualizaciones por lotes.

Para ADO, lo que debe hacer es fijar LockType del conjunto de datos a ltBatchOptimistic. Para UniDAC, debe establecer 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 enviarlos a alltogether base de datos sólo cuando se llama método UpdateBatch (ADO) o ApplyUpdates método (UniDAC).

Ahora lo que debe hacer es dejar que su usuario inserte/edite un registro en el conjunto de datos maestro y cualquier registro que desee en el conjunto de datos de detalles utilizando los componentes que le interesen. Todos los cambios se almacenarían en caché. Cuando finaliza su usuario, puede iniciar una nueva transacción y, en primer lugar, llamar a UpdateBatch (o ApplyUpdate en caso de UniDAC) para el conjunto de datos maestro, y luego para el conjunto de datos de detalles, y si todo va bien, confirmar la transacción.

Esto hará que sus transacciones sean breves sin necesitar la capa adicional de ClientDataset.

Saludos

5

Entiendo su pregunta, creo. Al abrir un TADODataSet con p. Ej. 10 filas de datos para editar en un formulario, con componentes con capacidad de datos, hay situaciones en las que desea almacenar en caché todos los cambios realizados en todas las 10 filas (y posiblemente eliminaciones e inserciones) y confirmarlo como un solo lote . No puede abrir la transacción en el primer cambio, ya que eso impediría que otros usuarios cambien los mismos datos. Las transacciones deben ser lo más cortas posible.

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

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

Ahora se almacenan en caché todos los cambios en TClientDataSet y puedes llamarlo método ApplyUpdates para publicar todos los cambios en una transacción rápida. Tenga en cuenta que también es posible usar múltiples TADODataSets y múltiples TClientDataSets para una estructura de detalle maestro (-detail-etc) con datasets anidados. Todos los cambios de detalles maestros también pueden almacenarse en caché y aplicarse en un lote en una transacción. Consulte la ayuda y los recursos en otros lugares para obtener todos los detalles sobre la implementación de esto. Al principio no es fácil. Pero si lo descubriste es fácil y ofrece toneladas de posibilidades. (Edición fuera de línea, el examen de los cambios antes de aplicarlos, etc.)

+0

Sí, su descripción es correcta. Gracias. Aunque parece bastante complejo, aprenderé sobre la cadena de componentes que mencionas como una posible solución. – Cocin

0

Transacciones debe ser tan corto como necesita. El problema es cómo las diferentes bases de datos manejan el bloqueo. Las bases de datos que realizan solo el bloqueo a nivel de fila y pueden regresar inmediatamente desde un bloqueo sin esperar tienen mucha menos probabilidad de estancamiento. Por lo general, las inserciones son menos problemáticas (aunque el otro usuario no verá nuevas filas hasta que se confirmen, según el nivel de aislamiento), las actualizaciones y las eliminaciones son más problemáticas. Comprometerse con demasiada frecuencia también podría ser "malo". Los cambios en el almacenamiento en caché y su aplicación en una sola operación es otra posibilidad, pero debe manejar los problemas debido a que otros usuarios cambian los registros mientras tanto. No existe una solución "mejor": todo depende de las necesidades reales. Para algunas aplicaciones (y algunas bases de datos) mantener el registro bloqueado mientras cambien está bien, para otros no. Las actualizaciones por lotes pueden estar bien en algunos escenarios y no en otros. Debe seleccionar el modelo que mejor se adapte a su aplicación y base de datos.

2

para evitar la necesidad de realizar grandes transacciones utilizo DataSetProviders y ClientDatasets (incluso a nivel local).

Considere utilizar esto como un tipo de caché y le ofrece lo mejor de ambos mundos. Puede usar controles de datos para simplificar las cosas mientras trabaja en la interfaz de usuario. Las acciones del usuario sobre los conjuntos de datos son "registradas" por los ClientDataSets (tipo de caché de base de datos).

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

En el escenario más simple, donde todos los conjuntos de datos están en relación maestro-detalle (anidados por el proveedor), el proveedor inicia y confirma/retrotrae la transacción por sí mismo, por lo que está en una situación de todo o nada automáticamente.

Si tiene relaciones más complejas, puede llamar 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 se llama a ApplyUpdates, luego no hace nada con la transacción, sino que simplemente publica los cambios en la base de datos, asumiendo que usted tiene el control de la transacción.

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

Mis 2 centavos.

1

Tiene toda la razón de que una transacción write debe ser lo más corta posible, y no debe estar activa todo el tiempo mientras un usuario está rellenando el formulario.

La solución general, como ya se ha respondido, es utilizar un nivel intermedio (un ClientDataSet). Pero el problema real con su escenario es que no puede obtener un valor de autoincrement para la tabla Master sin Master.Append y Master.Post y, en consecuencia, inicia una transacción write mucho antes de que realmente se requiera.

Así que si usted no desea utilizar el nivel intermedio y seguir utilizando componentes de datos con corto escritura 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 los componentes de acceso a datos FibPlus para Firebird soportan completamente esta característica.

+0

Algunas bases de datos fuerzan al usuario a usar transacciones muy cortas, porque no pueden manejar bien la concurrencia. Pero las transacciones están ahí para proteger la integridad y consistencia de los datos. Como Tom Kyte (asktom.oracle.com) escribió: "La transacción debe ser tan grande como deben ser [...] La transacción debe ser exactamente el tiempo necesario (pero no más). Las transacciones no están disponibles para la comodidad de la computadora o su software. Son para proteger sus datos ". –

Cuestiones relacionadas