Clase odbcConn (VFP)
(Difference between revisions)
VictorEspina (Talk | contribs) (Created page with "Es muy común ver en los foros de programación VFP preguntas tales como ''como trabajar con SQL Server?'', ''debo usar una conexión permanente o conectarme solo cuando lo ne...") |
VictorEspina (Talk | contribs) m (Categorizacion) |
||
Line 271: | Line 271: | ||
ENDDEFINE | ENDDEFINE | ||
</pre> | </pre> | ||
+ | |||
+ | |||
+ | [[Category:Visual FoxPro]] |
Revision as of 15:26, 21 February 2014
Es muy común ver en los foros de programación VFP preguntas tales como como trabajar con SQL Server?, debo usar una conexión permanente o conectarme solo cuando lo necesito?, y varias mas por el estilo. Aunque estos temas dan para mucha discusión, senti que mucho del problema se solucionaría si existiera una forma fácil de acceder a datos remotos y de manejar las conexiones con estas fuentes, tanto en forma conectada como en forma desconectada. Habiendo enfrentado estos temas decenas de veces en los últimos anos, decidí crear esta clase que resumen muchas de las practicas que yo mismo he venido implementando desde hace mas de 10 anos. La clase odbcConn hace unas pocas cosas:
- Permite abrir y cerrar una conexión con una fuente de datos ODBC
- Permite enviar comandos a esa conexión y obtener resultados (si los hubiera)
- Permite ejecutar esos comandos tanto en forma conectada como en forma desconectada (es decir, con conexión por demanda)
- Permite crear y cerrar transacciones sobre esa conexión.
He aquí el código; ojalá les sea de tanta utilidad como a mi.
* odbcConn (Clase) * Implementacion basica de un asistente para conexion con * fuentes de datos odbc y ejecucion de comandos tanto en * escenario conectados como desconectados * * Autor: V. Espina * Fecha: Feb 2014 * * CODIGO LIBRE - USELO BASO SU PROPIA RESPONSABILIDAD * * EJEMPLOS: * a) Establecer una conexion con un origen de datos: * * oConn = CREATEOBJECT("odbcConn", "string de conexion") * * * b) Obtener el contenido de una tabla en un cursor, usando modo desconectado. En este modo * la clase abre y cierra la conexion automaticamente: * * IF NOT oConn.Execute("SELECT * FROM clientes", "QCLIENTES") * MESSAGEBOX(oConn.lastError) * RETURN .F. * ENDIF * SELECT QCLIENTES * BROWSE * USE * * c) Obtener el contenido de un registro en una tabla, usando modo conectado. En este modo * la conexion se abre explicitamente y se mantiene abierta durante el tiempo necesario: * * IF NOT oConn.Open() * MESSAGEBOX(oConn.lastError) * RETURN .F. * ENDIF * oRow = oConn.executeRow("SELECT * FROM Clientes WHERE codigo = ?cCodigo") * ?oRow.codigo, oRow.nombre * oConn.Close() * * d) Manejo de transacciones: * * oConn.Open() * oConn.beginTransaction() * oConn.executeNonQuery(...) * oConn.executeNonQuery(...) * oConn.Commit() * oConn.Close() * #DEFINE TRUE .T. #DEFINE FALSE .F. DEFINE CLASS odbcConn AS Custom HIDDEN _nHandle && Handle de la conexion ODBC HIDDEN _cConnStr && String de conexion (interno) HIDDEN _cErrorMsg && Texto del ultimo error ocurrido connString = "" && String de conexion (Propiedad, S/L) Opened = .F. && Estado de la conexion (Propiedad, S/L) lastError = "" && Ultimo error ocurrid (Propiedad, S/L) PROCEDURE connString_Access && ConnString Getter/Setter RETURN THIS._cConnStr ENDPROC PROCEDURE connString_Assign(vNewVal) PROCEDURE Opened_Access && Opened Getter/Setter RETURN (THIS._nHandle <> 0) ENDPROC PROCEDURE Opened_Assign(vNewVal) PROCEDURE lastError_Access && LastError Getter/Setter IF EMPTY(THIS._cConnStr) RETURN "No se indico una cadena de conexion" ENDIF RETURN THIS._cErrorMsg ENDPROC PROCEDURE lastError_Assign(vNEwVal) * Constructor * PROCEDURE Init(pcConnString) THIS._cConnStr = pcConnString THIS._nHandle = 0 ENDPROC * Open * Abre una conexion * PROCEDURE Open IF THIS.Opened RETURN TRUE ENDIF IF EMPTY(THIS.connString) RETURN FALSE ENDIF LOCAL nResult nResult = SQLSTRINGCONNECT(THIS.connString) IF nResult > 0 THIS._nHandle = nResult ELSE THIS._cErrorMsg = THIS.getLastError() ENDIF RETURN (nResult > 0) ENDPROC * Close * Cierra una conexion * PROCEDURE Close IF THIS.Opened SQLDISCONNECT(THIS._nHandle) THIS._nHandle = 0 ENDIF ENDPROC * Execute * Ejecuta una instruccion SQL. Si no hay una conexion * abierta, se abre y se cierra automaticamente. * PROCEDURE Execute(pcSQL, pcCursor) LOCAL lAutoConn lAutoConn = (!THIS.Opened) IF lAutoConn IF NOT THIS.Open() RETURN FALSE ENDIF ENDIF LOCAL nResult IF !EMPTY(pcCursor) nResult = SQLEXEC(THIS._nHandle, pcSQL, pcCursor) ELSE nResult = SQLEXEC(THIS._nHandle, pcSQL) ENDIF IF nResult < 0 THIS._cErrorMsg = THIS.getLastError() ENDIF IF lAutoConn THIS.Close() ENDIF RETURN (nResult > 0) ENDPROC * executeNonQuery * Ejecuta una instruccion que no devuelve resultados * PROCEDURE executeNonQuery(pcSQL) RETURN THIS.Execute(pcSQL) ENDPROC * executeScalar * Ejecuta una instruccion y devuelve el valor de la primera * columna en el primer registro. Si el comando da un error * o no se encontraron resultados, se devuelve NULL * PROCEDURE executeScalar(pcSQL) LOCAL cCursor,uResult,nWkArea cCursor = SYS(2015) uResult = NULL nWkArea = SELECT() IF NOT THIS.Execute(pcSQL, cCursor) RETURN NULL ENDIF SELECT (cCursor) IF RECCOUNT() > 1 uResult = EVAL(FIELD(1)) ENDIF USE SELECT (nWkArea) RETURN uResult ENDPROC * executeRow * Ejecuta una instruccion y devuelve un objeto con los valores * del primer registro. Si el comando da un error o no se * encontraron resultados, se devuelve NULL * PROCEDURE executeRow(pcSQL) LOCAL cCursor,oResult,nWkArea cCursor = SYS(2015) oResult = NULL nWkArea = SELECT() IF NOT THIS.Execute(pcSQL, cCursor) RETURN NULL ENDIF SELECT (cCursor) IF RECCOUNT() > 1 SCATTER NAME oResult MEMO ENDIF USE SELECT (nWkArea) RETURN oResult ENDPROC * setDatabase * Establece una BD por omision en la conexion * PROCEDURE setDatabase(pcDBName) IF NOT THIS.Opened RETURN FALSE ENDIF RETURN THIS.executeNonQuery("USE " + pcDBName) ENDPROC * beginTransaction * Iniciar una transaccion en la conexion actual * PROCEDURE beginTransaction IF NOT THIS.Opened RETURN FALSE ENDIF RETURN THIS.executeNonQuery("BEGIN TRANSACTION") ENDPROC * Commit * Cierra una transaccion y guarda los cambios realizados * PROCEDURE Commit IF NOT THIS.Opened RETURN FALSE ENDIF RETURN THIS.executeNonQuery("COMMIT") ENDPROC * Rollback * Cierra una transaccion y descarta los cambios realizados * PROCEDURE Rollback IF NOT THIS.Opened RETURN FALSE ENDIF RETURN THIS.executeNonQuery("ROLLBACK") ENDPROC * getLastError (Hidden) * Devuelve la descripcion del ultimo error ocurrido * HIDDEN PROCEDURE getLastError LOCAL ARRAY aErrInfo[1] AERROR(aErrInfo) RETURN aErrInfo[2] ENDPROC ENDDEFINE