FoxPro/Visual FoxPro - Cursor SPT a vista remota

   
Vista:
Imágen de perfil de Mauricio

Cursor SPT a vista remota

Publicado por Mauricio (1367 intervenciones) el 08/12/2010 00:32:27
pueden buscar en http://www.portalfox.com/index.php?name=News&file=article&sid=2122
*
Como convertir un cursor SPT (SQL Pass-Thru) en una vista remota para hacer más fáciles las actualizaciones a los datos. Una vista remota es un cursor SQL Pass-Thru (SPT) con un "envoltorio de vista" especial que permite que el cursor remoto responda a las funciones TABLEUPDATE(), TABLEREVERT() y REQUERY() de VFP, haciendo más fáciles las actualizaciones a los datos (sin necesidad de escribir tediosas declaraciones SQL INSERT, UPDATE y DELETE).

Sin embargo, algunos desarrolladores VFP sienten que SPT es superior a las vistas remotas, y quieren hacer el trabajo extra necesario para escribir el código de las actualizaciones. Ellos también pueden preferir reducir su mantenimiento adicional, eliminando vistas remotas de un contenedor de base de datos de VFP.

Este artículo demuestra que usted puede usar la función CURSORSETPROP() para convertir un cursor SPT en una vista remota, la cual puede ser actualizada facilmente utilizando la función TABLEUPDATE().

El siguiente PRG demuestra esta técnica, usando la tabla Authors (Autores) de la base de datos Pubs (Publicaciones), contenida en los ejemplos de SQL Server. A fin de ejecutar el PRG con éxito, tendrá que modificar la línea SQLSTRINGCONNECT() para especificar una cadena de conexión que funcione en su computadora.

El procedimiento local RemoteSPTCursor2RemoteView() en el PRG, es una rutina genérica que convierte cualquier cursor SPT en una "vista remota", con lo cual las actualizaciones son fácilmente llevadas a cabo con una simple llamada TABLEUPDATE().

La única diferencia entre un cursor SPT convertido en una vista remota en tiempo de ejecución y una vista remota existente (contenida en una base de datos de VFP) es que no puede hacer un REQUERY() a un cursor SPT convertido en una vista remota. Toda la configuración CURSORGETPROP() funciona, el almacenamiento en buffer (y las funciones permitidas) funcionan, y hasta la función REFRESH() funciona.

Este artículo se aplica a todas las versiones de VFP, pero el siguiente código, requiere VFP 7.0 o superior.

*
* Ejemplo de convertir un cursor SPT en una "vista remota"
*
* El código interesante está en el procedimiento local
* RemoteSPTCursor2RemoteView(), que hace todo el
* trabajo, y que puede modificar para su propio uso
*
CLEAR
LOCAL lnHandle, lnGNM
*
* IMPORTANTE!
* La línea siguiente del código tendrá que ser modificada
* para especificar una cadena válida SQLSTRINGCONNECT()
* para establecee una conexión a la base de datos Pubs
*
WAIT WINDOW "Intentanto conectar a la base de datos Pubs." + CHR(13) + ;
"Si este intento falla, debera modificar el programa en " + CHR(13) + ;
"la línea SQLSTRINGCONNECT(<string>) para especificar una " + CHR(13) + ;
"cadena de conexión que funcione en su computadora." NOWAIT
*
lnHandle = SQLSTRINGCONNECT("DRIVER=sql server;SERVER=(local);UID=sa;PWD=;DATABASE=Pubs")
*
WAIT CLEAR
IF lnHandle < 1
MESSAGEBOX("No puede establecer una conexión a la base de datos Pubs en " + ;
"SQL Server. Modifique la línea SQLSTRINGCONNECT() para especificar " + ;
"una cadena de conexión que funcione en su computadora.", 16, "Aviso")
RETURN
ENDIF
IF SQLEXEC(lnHandle,"SELECT * FROM AUTHORS ORDER BY Au_LName") < 0
MESSAGEBOX("No puede hacer SELECT * FROM AUTHORS", 16, "Aviso")
SQLDISCONNECT(0)
RETURN
ENDIF
SELECT SQLResult
*
* Aquí está donde convertimos el cursor SPT en una vista remota
*
IF NOT RemoteSPTCursor2RemoteView("SQLResult", "Authors", "Au_ID", 5)
MESSAGEBOX("No puede convertir SQLResult en una vista remota.", 16, "Aviso")
SQLDISCONNECT(0)
RETURN
ENDIF
WAIT WINDOW "Haga cambios a los datos," + CHR(13) + ;
"(Insert/Update/Delete)" + CHR(13) + ;
"y cierre la ventana Examinar" NOWAIT NOCLEAR
BROWSE LAST
WAIT CLEAR
lnGNM = GETNEXTMODIFIED(0,"SQLResult")
IF lnGNM = 0
MESSAGEBOX("El buffer esta limpio, aparentemente no hizo cambios.", 48, "Aviso")
ELSE
*
* El buffer esta 'sucio'
*
GOTO (lnGNM)
MESSAGEBOX('GetNextModified(0,"SQLResult"): ' + ;
TRANSFORM(GETNEXTMODIFIED(0,"SQLResult")) + CHR(13) + ;
'GetFldState(-1,"SQLResult"): ' + TRANSFORM(GETFLDSTATE(-1,"SQLResult")) + CHR(13) + ;
'Presione "OK" para intentar el TABLEUPDATE(.t.,.t.,"SQLResult")', 48, "Aviso")
IF TABLEUPDATE(.T.,.T.,"SQLResult")
*
* Tuvo éxito!
*
MESSAGEBOX("Todas las modificaciones se hicieron exitosamente " + ;
"con TABLEUPDATE() - La ventana Examinar muestra " + ;
"un nuevo SELECT * FROM AUTHORS.", 48, "Please Note")
SQLEXEC(lnHandle,"SELECT * FROM AUTHORS ORDER BY Au_LName")
WAIT WINDOW "Nuevo " + CHR(13) + "SELECT * FROM AUTHORS" + CHR(13) + ;
"conteniendo cualquier cambio " + CHR(13) + "que Ud. hizo." NOWAIT NOCLEAR
BROWSE LAST
WAIT CLEAR
ELSE
*
* Falló
*
LOCAL laError[1]
AERROR(laError) &&& laError[1] = 1526
MESSAGEBOX("El TABLEUPDATE() falló porque " + ;
TRANSFORM(laError[2]) + "/" + TRANSFORM(laError[3]), 16, "Aviso")
ENDIF
ENDIF
SQLDISCONNECT(0)
RETURN
*
* --
*
PROCEDURE RemoteSPTCursor2RemoteView
*
* Convierte un cursor SPT en un vista remota actualizable
*
* lParameters
*
* tcCursorAlias (R) Alias del cursor SPT
* tcTableName (R) Nombre de la tabla remota de la cual
* tcCursorAlias fue recuperado
* tcPKFieldName (R) Nombre del campo en tcCursorAlias
* que es la llave (primaria)
* tnBuffering (O) Especifica el modo de almacenamiento de buffer
* para tcCursorAlias,
* por defecto 3 - Optimista de Tabla
* tnWhereType (O) Especifica la propiedad WhereType,
* por defecto 3 - Clave y Modificado
* tlExcludePK (O) Bandera lógica que indica si hay que excluir el
* campo de PK del UpdatableFieldList - pasa este
* parámetro como .T. cuando el campo de PK es
* poblado en virtud de ser una columna de Identidad
*
LPARAMETERS tcCursorAlias, tcTableName, tcPKFieldName, ;
tnBuffering, tnWhereType, tlExcludePK
*
* propiedades de actualización - UpdateNameList y
* UpdatableFieldList, igual que una vista remota
*
LOCAL lnSelect, lcUpdatableFieldList, lcUpdateNameList, ;
lcField, xx, lnCount, llSuccess
lcUpdatableFieldList = SPACE(0)
lcUpdateNameList = SPACE(0)
lcField = SPACE(0)
lnSelect = SELECT(0)
lnCount = 0
SELECT (tcCursorAlias)
*
* añadir cada campo al UpdateNameList y
* las propiedades UpdatableFieldList
*
FOR xx = 1 TO FCOUNT()
lcField = UPPER(ALLTRIM(FIELD(xx)))
lnCount = lnCount + 1
lcUpdatableFieldList = lcUpdatableFieldList + ;
IIF(lnCount=1,SPACE(0),",") + lcField
lcUpdateNameList = lcUpdateNameList + ;
IIF(lnCount=1,SPACE(0),",") + lcField + ;
SPACE(1) + tcTableName + "." + lcField
ENDFOR
IF tlExcludePK
*
* Cuando las PKs no deben ser generadas a mano
* (como cuando el PK es una columna Identity),
* el campo PK tiene que ser quitado del
* UpdatableFieldList para prevenir un TableUpdate()
* e intentar actualizar el campo PK, que
* causaría un crash
*
* ... por cualquier razón, el campo de PK
* debe permanecer en el UpdateNameList...
*
lcUpdatableFieldList = "," + ALLTRIM(lcUpdatableFieldList) + ","
lcUpdatableFieldList = STRTRAN(lcUpdatableFieldList, ;
"," + UPPER(tcPKFieldName) + "," , ",")
*
* asegurar que no dejamos una coma durante
* el principio o el final de la cadena
*
IF LEFTC(lcUpdatableFieldList,1) = ","
lcUpdatableFieldList = SUBSTRC(lcUpdatableFieldList,2)
ENDIF
IF RIGHTC(lcUpdatableFieldList,1) = ","
lcUpdatableFieldList = LEFTC(lcUpdatableFieldList,LENC(lcUpdatableFieldList)-1)
ENDIF
ENDIF
llSuccess = .F.
DO CASE
CASE NOT CURSORSETPROP("KeyFieldList",tcPKFieldName)
ASSERT .F. MESSAGE PROGRAM() + " no se puede configurar KeyFieldList"
CASE NOT CURSORSETPROP("Tables",tcTableName)
ASSERT .F. MESSAGE PROGRAM() + " no se puede configurar Tables"
CASE NOT CURSORSETPROP("UpdatableFieldList",lcUpdatableFieldList)
ASSERT .F. MESSAGE PROGRAM() + " no se puede configurar UpdatableFieldList"
CASE NOT CURSORSETPROP("UpdateNameList",lcUpdateNameList)
ASSERT .F. MESSAGE PROGRAM() + " no se puede configurar UpdateNameList"
CASE NOT CURSORSETPROP("WhereType", ;
IIF(VARTYPE(tnWhereType)="N",tnWhereType,3))
ASSERT .F. MESSAGE PROGRAM() + " no se puede configurar WhereType"
CASE NOT CURSORSETPROP("Buffering", ;
IIF(VARTYPE(tnBuffering)="N",tnBuffering,3))
ASSERT .F. MESSAGE PROGRAM() + " no se puede configurar Buffering"
CASE NOT CURSORSETPROP("SendUpdates",.T.)
ASSERT .F. MESSAGE PROGRAM() + " no se puede configurar SendUpdates"
OTHERWISE
llSuccess = .T.
ENDCASE
SELECT (lnSelect)
RETURN llSuccess
ENDPROC</string>
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder