Persistente derivados de atributos
Un pequeño ejemplo de lo que la deriva de los atributos que se conservan en la base de datos.
Persistentes derivadas de los atributos de Negrita
Negrita se deriva de los atributos siempre se evalúan en la memoria, esto hace que sea imposible llevar a cabo una InPS (persistencia de almacenamiento) de búsqueda en contra de ciertos datos. Cualquier expresión de búsqueda que se refiere a una cualidad derivada hará Negrita para cargar todos los objetos de la base de datos en la memoria de la primera de una memoria evalution, esto puede ser muy lento y consume recursos.
los Últimos debates han sido publicados en los grupos de apoyo preguntando cómo lograr derivados de atributos que son también sobrevivieron a la DB para SQL evaluación. Hoy he tenido el mismo requisito, y esta es la solución que se me ocurrió.
La primera cosa a hacer es evitar que marca el atributo de la derivada en el modelo. En su lugar, hacer que el atributo un atributo persistente, por ejemplo,
& nbsp & nbsp Nombre: string (128)
El siguiente paso es asegurarse de que el valor de FullName es siempre hasta la fecha, por lo que es necesario reemplazar ReceiveEventFromOwned en cada clase descendiente creamos.
procedimiento TPerson.ReceiveEventFromOwned((Autor: TObject OriginalEvent: TBoldEvent) begin & nbsp & nbsp heredado & nbsp & nbsp si (OriginalEvent = beCompleteModify) y (Autor = M_Name) entonces & nbsp & nbsp & nbsp & nbsp FullName := M_FirstName.AsString '' M_LastName.AsString fin
|
Esto se asegurará de que el atributo es siempre hasta la fecha, pero la debilidad de aquí, que ahora vamos a abordar, es que es posible alterar la FullName manualmente. Para resolver este problema necesitamos hacer FullName de sólo lectura, como así
función TPerson.ReceiveQueryFromOwned(Autor: TObject OriginalEvent: TBoldEvent const Args: array de const Suscriptor: TBoldSubscriber): Boolean begin & nbsp & nbsp Resultado := heredado ReceiveQueryFromOwned(Originador, OriginalEvent, Args, el Suscriptor) & nbsp & nbsp si no Resultado o BoldObjectIsDeleted entonces Salir & nbsp & nbsp si (Autor = M_FullName) y (OriginalEvent = bqMayModify) & nbsp & nbsp begin & nbsp & nbsp & nbsp & nbsp Resultado := False & nbsp & nbsp & nbsp & nbsp //error Inesperado & nbsp & nbsp & nbsp & nbsp SetBoldLastFailureReason(TBoldFailureReason.Create('FullName es inmutable', Self)) & nbsp & nbsp fin fin
|
FullName ya no pueden ser modificados, por desgracia, el error que hemos introducido es que ya no podemos establecer el valor de FullName en la derivación de código.
Para resolver este último problema necesitamos una forma de identificación de usuario/normal-cambios de código y el 'interno' de los cambios. Para ello siempre me implementar un patrón común de mi base de objeto, como por lo que
1) Crear un Delphi atributo - InternalChangeCount: Integer
2) Agregar un método protegido BeginInternalChange
3) Agregar un método protegido EndInternalChange
4) Agregar un método protegido IsInternalChange: Boolean
//Nota: TRootObject es el objeto raíz de mi modelo procedimiento TRootObject.BeginInternalChange begin
& nbsp & nbsp Inc(fInternalChangeCount) fin procedimiento TRootObject.EndInternalChange begin & nbsp & nbsp si fInternalChangeCount = 0 entonces & nbsp & nbsp & nbsp & nbsp aumentar de Excepción.Create('EndInternalChange sin BeginInternalChange') & nbsp & nbsp Dic(fInternalChangeCount) fin función TRootObject.IsInternalChange: Boolean begin & nbsp & nbsp Resultado := (InternalChangeCount > 0) fin
|
por último, sólo tenemos que actualizar el código fuente original de modo que
1) Ajuste de la deriva de código se realiza dentro de un 'cambio interno'
2) Modificaciones a FullName está permitida si el cambio es interno.
procedimiento TPerson.ReceiveEventFromOwned(Autor: TObject OriginalEvent: TBoldEvent) begin & nbsp & nbsp heredado & nbsp & nbsp si OriginalEvent = beCompleteModify entonces & nbsp & nbsp begin & nbsp & nbsp & nbsp & nbsp si (Autor = M_FirstName) o (Autor = M_LastName) entonces & nbsp & nbsp & nbsp & nbsp prueba & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp BeginInternalChange & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp FullName := M_FirstName.AsString '' M_LastName.AsString & nbsp & nbsp & nbsp & nbsp finalmente & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp EndInternalChange & nbsp & nbsp & nbsp & nbsp fin & nbsp & nbsp fin fin función TPerson.ReceiveQueryFromOwned(Autor: TObject OriginalEvent: TBoldEvent const Args: array de const Suscriptor: TBoldSubscriber): Boolean begin & nbsp & nbsp Resultado := heredado ReceiveQueryFromOwned(Originador, OriginalEvent, Args, el Suscriptor) & nbsp & nbsp si no Resultado o BoldObjectIsDeleted entonces Salir & nbsp & nbsp si (Autor = M_FullName) y (OriginalEvent = bqMayModify) & nbsp & nbsp begin & nbsp & nbsp & nbsp & nbsp si IsInternalChange entonces & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Resultado := True & nbsp & nbsp & nbsp & nbsp persona & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Resultado := False & nbsp & nbsp & nbsp & nbsp //error Inesperado & nbsp & nbsp & nbsp & nbsp si no Resultado & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp SetBoldLastFailureReason(TBoldFailureReason.Create('FullName es inmutable', Self)) & nbsp & nbsp fin fin
|
En la aplicación que estoy creando el objeto de la estructura es como sigue:
& nbsp & nbsp RootObject (ModelRoot)
& nbsp & nbsp & nbsp & nbsp RoledObject (Tiene un FullName)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Persona (FullName = FirstName '' LastName)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Departamento (Nombrecompleto = Nombre)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Empresa (Nombrecompleto = Nombre)
Conclusión:
Esta técnica requiere sólo una pequeña pieza de código para cada clase descendiente (RecevieEventFromOwned), mientras que proporciona la capacidad de realizar búsquedas en la base de datos del servidor en contra de una cualidad derivada. Creo que los beneficios superan con creces la pequeña cantidad de trabajo necesario para lograr de ellos.
Persistente derivados de atributos
Persistente derivados de atributos : Multi-millones de consejos para hacer su vida mas facil.
Un pequeño ejemplo de lo que la deriva de los atributos que se conservan en la base de datos.
Persistentes derivadas de los atributos de Negrita
Negrita se deriva de los atributos siempre se evaluan en la memoria, esto hace que sea imposible llevar a cabo una InPS (persistencia de almacenamiento) de busqueda en contra de ciertos datos. Cualquier expresion de busqueda que se refiere a una cualidad derivada hara Negrita para cargar todos los objetos de la base de datos en la memoria de la primera de una memoria evalution, esto puede ser muy lento y consume recursos.
los Ultimos debates han sido publicados en los grupos de apoyo preguntando como lograr derivados de atributos que son tambien sobrevivieron a la DB para SQL evaluacion. Hoy he tenido el mismo requisito, y esta es la solucion que se me ocurrio.
La primera cosa a hacer es evitar que marca el atributo de la derivada en el modelo. En su lugar, hacer que el atributo un atributo persistente, por ejemplo,
& nbsp & nbsp Nombre: string (128)
El siguiente paso es asegurarse de que el valor de FullName es siempre hasta la fecha, por lo que es necesario reemplazar ReceiveEventFromOwned en cada clase descendiente creamos.
procedimiento TPerson.ReceiveEventFromOwned((Autor: TObject OriginalEvent: TBoldEvent) begin & nbsp & nbsp heredado & nbsp & nbsp si (OriginalEvent = beCompleteModify) y (Autor = M_Name) entonces & nbsp & nbsp & nbsp & nbsp FullName := M_FirstName.AsString '' M_LastName.AsString fin
|
Esto se asegurara de que el atributo es siempre hasta la fecha, pero la debilidad de aqui, que ahora vamos a abordar, es que es posible alterar la FullName manualmente. Para resolver este problema necesitamos hacer FullName de solo lectura, como asi
funcion TPerson.ReceiveQueryFromOwned(Autor: TObject OriginalEvent: TBoldEvent const Args: array de const Suscriptor: TBoldSubscriber): Boolean begin & nbsp & nbsp Resultado := heredado ReceiveQueryFromOwned(Originador, OriginalEvent, Args, el Suscriptor) & nbsp & nbsp si no Resultado o BoldObjectIsDeleted entonces Salir & nbsp & nbsp si (Autor = M_FullName) y (OriginalEvent = bqMayModify) & nbsp & nbsp begin & nbsp & nbsp & nbsp & nbsp Resultado := False & nbsp & nbsp & nbsp & nbsp //error Inesperado & nbsp & nbsp & nbsp & nbsp SetBoldLastFailureReason(TBoldFailureReason.Create('FullName es inmutable', Self)) & nbsp & nbsp fin fin
|
FullName ya no pueden ser modificados, por desgracia, el error que hemos introducido es que ya no podemos establecer el valor de FullName en la derivacion de codigo.
Para resolver este ultimo problema necesitamos una forma de identificacion de usuario/normal-cambios de codigo y el 'interno' de los cambios. Para ello siempre me implementar un patron comun de mi base de objeto, como por lo que
1) Crear un Delphi atributo - InternalChangeCount: Integer
2) Agregar un metodo protegido BeginInternalChange
3) Agregar un metodo protegido EndInternalChange
4) Agregar un metodo protegido IsInternalChange: Boolean
//Nota: TRootObject es el objeto raiz de mi modelo procedimiento TRootObject.BeginInternalChange begin
& nbsp & nbsp Inc(fInternalChangeCount) fin procedimiento TRootObject.EndInternalChange begin & nbsp & nbsp si fInternalChangeCount = 0 entonces & nbsp & nbsp & nbsp & nbsp aumentar de Excepcion.Create('EndInternalChange sin BeginInternalChange') & nbsp & nbsp Dic(fInternalChangeCount) fin funcion TRootObject.IsInternalChange: Boolean begin & nbsp & nbsp Resultado := (InternalChangeCount > 0) fin
|
por ultimo, solo tenemos que actualizar el codigo fuente original de modo que
1) Ajuste de la deriva de codigo se realiza dentro de un 'cambio interno'
2) Modificaciones a FullName esta permitida si el cambio es interno.
procedimiento TPerson.ReceiveEventFromOwned(Autor: TObject OriginalEvent: TBoldEvent) begin & nbsp & nbsp heredado & nbsp & nbsp si OriginalEvent = beCompleteModify entonces & nbsp & nbsp begin & nbsp & nbsp & nbsp & nbsp si (Autor = M_FirstName) o (Autor = M_LastName) entonces & nbsp & nbsp & nbsp & nbsp prueba & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp BeginInternalChange & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp FullName := M_FirstName.AsString '' M_LastName.AsString & nbsp & nbsp & nbsp & nbsp finalmente & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp EndInternalChange & nbsp & nbsp & nbsp & nbsp fin & nbsp & nbsp fin fin funcion TPerson.ReceiveQueryFromOwned(Autor: TObject OriginalEvent: TBoldEvent const Args: array de const Suscriptor: TBoldSubscriber): Boolean begin & nbsp & nbsp Resultado := heredado ReceiveQueryFromOwned(Originador, OriginalEvent, Args, el Suscriptor) & nbsp & nbsp si no Resultado o BoldObjectIsDeleted entonces Salir & nbsp & nbsp si (Autor = M_FullName) y (OriginalEvent = bqMayModify) & nbsp & nbsp begin & nbsp & nbsp & nbsp & nbsp si IsInternalChange entonces & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Resultado := True & nbsp & nbsp & nbsp & nbsp persona & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Resultado := False & nbsp & nbsp & nbsp & nbsp //error Inesperado & nbsp & nbsp & nbsp & nbsp si no Resultado & nbsp & nbsp & nbsp & nbsp & nbsp & nbsp SetBoldLastFailureReason(TBoldFailureReason.Create('FullName es inmutable', Self)) & nbsp & nbsp fin fin
|
En la aplicacion que estoy creando el objeto de la estructura es como sigue:
& nbsp & nbsp RootObject (ModelRoot)
& nbsp & nbsp & nbsp & nbsp RoledObject (Tiene un FullName)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Persona (FullName = FirstName '' LastName)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Departamento (Nombrecompleto = Nombre)
& nbsp & nbsp & nbsp & nbsp & nbsp & nbsp Empresa (Nombrecompleto = Nombre)
Conclusion:
Esta tecnica requiere solo una pequeña pieza de codigo para cada clase descendiente (RecevieEventFromOwned), mientras que proporciona la capacidad de realizar busquedas en la base de datos del servidor en contra de una cualidad derivada. Creo que los beneficios superan con creces la pequeña cantidad de trabajo necesario para lograr de ellos.
Persistente derivados de atributos
By Consejos Y Trucos
Persistente derivados de atributos : Multi-millones de consejos para hacer su vida más fácil.