Accediendo a datos de VFP 9.0 desde la Web con el Proveedor OLE DB de VFP 9.0

Por Luis María Guayán

downlanim.gif Descargar ejemplos de este artículo (6 KB).

Contenido

 Introducción
 ¿Qué necesitamos?
 Algunos conceptos previos
 Nuestra primer página
 Utilizando procedimientos almacenados
 Modificando los datos de las tablas
 Para tener en cuenta
 Conclusión

Introducción

A partir de Visual FoxPro 9.0 tenemos una nueva opción para publicar los datos de nuestras tablas en la Web. Esta opción la logramos sin adquirir ni descargar ninguna herramienta de terceras partes, ni desarrollar objetos COM con Visual FoxPro. En este artículo veremos cómo desarrollar esta opción, con el uso de procedimientos almacenados en nuestra base de datos, el uso de una nueva función incluída en Visual FoxPro 9.0 y el nuevo Proveedor OLE DB de Visual FoxPro 9.0.

 

¿Qué necesitamos?

Suponemos en este artículo que tienes conocimientos sobre Microsoft Internet Information Server (IIS) y cómo crear aplicaciones con Active Server Pages (ASP).

Lo que necesitamos para desarrollar este breve y funcional ejemplo es:

  1. Una PC servidora con Internet Information Server (IIS) instalado en donde montaremos nuestro sitio Web. Si tienes poca experiencia en esto puedes consultar el artículo "Configurando IIS."

  2. Visual FoxPro 9.0 instalado o solamente el Proveedor OLE DB de Visual FoxPro 9.0; lo puedes descargar de Microsoft OLE DB Provider for Visual FoxPro 9.0.

    Como parte de lo nuevo que trae el Proveedor OLE DB de Microsoft para Visual FoxPro 9.0, y que utilizaremos en este ejemplo, podemos mencionar:

    • Los procedimientos almacenados pueden ahora retornar RecordSets creados a partir de cursores de VFP usando las nuevas funciones de la versión 9: SETRESULTSET(), GETRESULTSET() y CLEARRESULTSET().

    • Se actualizó la base de datos Northwind con 5 procedimientos almacenados que incluyen la función SETRESULTSET(), de modo que éstos retornan RecorSets cuando se ejecutan.

  3. Microsoft Data Access Components (MDAC) versión 2.6 ó superior. La última versión de MDAC la puedes descargar de  MDAC 2.8 (Español).

  4. Disponer de un editor de páginas ASP como Visual InterDev, FrontPage o simplemente el Block de Notas de Windows.

 

Algunos conceptos previos

¿Que es el Proveedor OLE DB de Visual FoxPro?
OLE DB (Object Linking and Embedding for DataBases) para Visual FoxPro es un componente COM que se utiliza para tener acceso a las bases de datos y tablas de VFP desde otros lenguajes de programación u otras aplicaciones. OLE DB no se utiliza directamente sino por medio de ADO (ActiveX Data Object). Este permite conectarse a orígenes de datos compatibles con OLE DB u ODBC (Open DataBase Connectivity). ADO está formado por varios objetos organizados de forma jerárquica y cada uno de éstos posee sus métodos y propiedades.

Veamos los 2 objetos de ADO que utilizaremos en el ejemplo:

  • Connection Object: Nos proporciona una conexión a una base de datos. Esta conexión nos permitirá ejecutar los distintos comandos sobre la base de datos. Connection es el objeto primario de ADO; ninguno de los otros objetos puede existir si éste no es declarado. La conexión terminará cuando ejecutamos el método Close o cuando termine la ejecución de la página ASP.

  • Recordset Object: Representa el resultado de una consulta ejecutada contra la base de datos. Este objeto es la interfaz natural contra la base de datos.

 

Nuestra primer página

Una vez instalado y corriendo el servicio de IIS, e instalado el Proveedor OLE DB de VFP en el servidor, creamos una carpeta ("\vfp") bajo el sitio Web predeterminado (por defecto "C:\Inetpub\wwwroot\") y ésta será nuestra carpeta o sitio de trabajo. En esta nueva carpeta creamos nuestra primera página ASP con el nombre "vfpoledb.asp" con el siguiente contenido:

<%@ Language=VBScript%>
<%
Dim Ruta, oConn, oRs
'-- Si solo tenemos instalado el proveedor OLE DB de VFP 9.0
' Ruta = "C:\Archivos de programa\" & _
' "Microsoft Visual FoxPro OLE DB Provider\Samples\Northwind\Northwind.DBC"
 
'-- Si tenemos instalado Visual FoxPro 9.0
Ruta = "C:\Archivos de programa\" & _
"Microsoft Visual FoxPro 9\Samples\Northwind\Northwind.DBC"
 
Set oConn = CREATEOBJECT("ADODB.Connection")
Set oRs = CREATEOBJECT("ADODB.RecordSet")
oConn.Open("Provider=VFPOLEDB.1;Data Source=" & Ruta)
oRs.Open "SELECT CustomerId, CompanyName, Address, City, Country FROM Customers", oConn
%>
<html>
<body>
<h3>Listado de Clientes al: <% =Now() %></h3>
<table border=1 width=100% cellspacing="1" cellpadding="2">
<tr>
<% For i = 0 to oRS.Fields.Count - 1 %>
<th><% = UCASE(oRS(i).Name) %></th>
<% Next %>
</tr>
<% Do While Not oRS.EOF %>
<tr bgcolor="#FFFFFF">
<% For i = 0 to oRS.Fields.Count - 1 %>
<td><% = oRS(i) %></td>
<% Next %>
</tr>
<%
oRs.MoveNext
Loop
oRs.Close
oConn.Close 
Set oRs = Nothing
Set oConn = Nothing
%>
</table>
</body>
</html>

Guardamos los cambios y desde el Explorador de Internet, ejecutamos:

https://localhost/vfp/vfpoledb.asp

Si todo va bien, estaremos visualizando la página que se muestra en la Figura 1.

Bb972247.art239-img01-570x316(es-es,MSDN.10).gif
Figura 1. Volver al texto.

¿Fácil? Ahora ya sabemos cómo podemos hacer nuestras páginas consultando dinámicamente los datos de nuestras tablas de VFP y publicarlas en la Web. Para no repetir el código de creación y apertura de nuestro objeto Connection en todas nuestras páginas, vamos a utilizar los Include que nos permiten las páginas ASP y en caso de cambiar la ruta o el nombre de nuestra base de datos, solo deberemos cambiar en un sólo lugar. Esto también le dará más seguridad a nuestro código.

Creamos una nueva página que llamaremos "conn.asp" y copiamos el siguiente código:

<%
Dim cRuta, oConn
'-- Si tenemos instalado Visual FoxPro 9.0
cRuta = "C:\Archivos de programa\" & _
"Microsoft Visual FoxPro 9\Samples\Northwind\Northwind.DBC"
 
Set oConn = CREATEOBJECT("ADODB.Connection")
oConn.Open("Provider=VFPOLEDB.1;Data Source=" & cRuta & ";Mode=ReadWrite")
%>

Cambiamos el código de la página "vfpoledb.asp" y la guardamos como "vfpoledb2.asp".

<%@ Language=VBScript%>
<!-- #include file="conn.asp" -->
<%
Dim oRs
Set oRs = CREATEOBJECT("ADODB.RecordSet")
oRs.Open "SELECT CustomerId, CompanyName, Address, City, Country FROM Customers", oConn
%>
<html>
<body bgcolor="#E0EAFC">
<h3>Listado de Clientes al: <% =Now() %></h3>
<table border=1 width=100% cellspacing="1" cellpadding="2">
<tr>
<% For i = 0 to oRS.Fields.Count - 1 %>
<th><% = UCASE(oRS(i).Name) %></th>
<% Next %>
</tr>
<% Do While Not oRS.EOF %>
<tr bgcolor="#FFFFFF">
<% For i = 0 to oRS.Fields.Count - 1 %>
<td><% = oRS(i) %></td>
<% Next %>
</tr>
<%
oRs.MoveNext
Loop
oRs.Close
oConn.Close 
Set oRs = Nothing
Set oConn = Nothing
%>
</table>
</body>
</html>

Ejecutamos desde el Explorador de Internet:

https://localhost/vfp/vfpoledb2.asp

Y veremos los mismos resultados que en el ejemplo anterior.

 

Utilizando procedimientos almacenados

Para nuestro ejemplo utilizaremos los procedimientos almacenados actualizados que trae Visual FoxPro 9.0 en la base de datos Northwind y crearemos algunos nuevos procedimientos almacenados. Para crear nuestro procedimiento almacenado, abrimos la base de datos y editamos los procedimientos almacenados:

OPEN DATABASE (HOME(2) + "Northwind\Northwind")
MODIFY PROCEDURE

Al final del archivo, escribimos nuestro procedimiento almacenado llamado CustomersAll, el cual nos retornará todos los registros de la tabla Customers:

PROCEDURE CustomersAll
SELECT CustomerId, CompanyName, Address, City, Country ;
FROM Customers ;
INTO CURSOR CustomersAll
RETURN SETRESULTSET("CustomersAll")
ENDPROC

El código para llamar un procedimiento almacenado de nuestra base de datos, desde la página ASP, es el siguiente:

<%
Dim cRuta, oConn
Ruta = "C:\Archivos de programa\" & _
"Microsoft Visual FoxPro 9\Samples\Northwind\Northwind.DBC"
Set oConn = CREATEOBJECT("ADODB.Connection")
oConn.Open("Provider=VFPOLEDB.1;Data Source=" & cRuta)
 
Dim oRS, nReg
Set oRs = oConn.Execute("CustomersAll",nReg,4)
%>

Creamos la nueva página customers.asp para obtener todos los registros de la tabla Customers, esta vez llamando al procedimiento almacenado creado anteriormente. En esta página agregamos código HTML para enlazar con las siguientes páginas que realizaremos para completar este ejemplo. El código de esta nueva página es:

<%@ Language=VBScript%>
<!-- #include file="conn.asp" -->
<%
Dim oRs, nReg
Set oRs = oConn.Execute("CustomersAll",nReg,4)
%>
<html>
<body bgcolor="#E0EAFC">
<h3>Listado de Clientes al: <% =Now() %></h3>
<table border=1 width=100% cellspacing="1" cellpadding="2">
<tr>
<th>Id</th>
<th>Compañia</th>
<th>Dirección</th>
<th>Ciudad</th>
<th>País</th>
</tr>
<% Do While Not oRS.EOF %>
<tr bgcolor="#FFFFFF">
<td><a href="/vfp/orders.asp?cId=<%=oRs(0)%>"><%=oRs(0)%></a></td>
<td><%=oRs(1)%></td>
<td><%=oRs(2)%></td>
<td><%=oRs(3)%></td>
<td><%=oRs(4)%></td>
</tr>
<%
oRs.MoveNext
Loop
oRs.Close
oConn.Close 
Set oRs = Nothing
Set oConn = Nothing
%>
</table>
<p>Registros: <%=nReg%></p>
</body>
</html>

Al ejecutar la página customers.asp nos muestra la tabla que se muestra en la Figura 2.

Bb972247.art239-img02-570x316(es-es,MSDN.10).gif
Figura 2. Volver al texto.

Como se puede apreciar en en la Figura 2, hemos creado un enlace a la página orders.asp pasando como parámetro el Id del cliente. El código de esta página es el que se muestra a continuación; éste llama al procedimiento almacenado CustOrdersOrders, que ya está incluido en la base de datos Northwind, con el parámetro del Id del cliente:

<%@ Language=VBScript%>
<!-- #include file="conn.asp" -->
<%
Dim cId
cId = Request("cId")
Dim oRs, nReg
Set oRs = oConn.Execute("CustOrdersOrders('" + cId + "')",nReg,4)
%>
<html>
<body bgcolor="#E0EAFC">
<h3>Ordenes del cliente <%=cId%></h3>
<table border=1 width=100% cellspacing="1" cellpadding="2">
<tr>
<th>Orden Id</th>
<th>Fecha Orden</th>
<th>Fecha Pedido</th>
<th>Fecha Envio</th>
</tr>
<% Do While Not oRS.EOF %>
<tr bgcolor="#FFFFFF">
<td><a href="/vfp/details.asp?oId=<%=oRs(0)%>"><%=oRs(0)%></a></td>
<td><%=oRs(1)%></td>
<td><%=oRs(2)%></td>
<td><%=oRs(3)%></td>
</tr>
<%
oRs.MoveNext
Loop
oRs.Close
oConn.Close 
Set oRs = Nothing
Set oConn = Nothing
%>
</table>
<p>Registros: <%=nReg%></p>
<p><a href="javascript:history.back()">Página&nbsp;anterior</a></p>
</body>
</html>

Los resultados de la ejecución de la página orders.asp son los que se muestran en la Figura 3.

Bb972247.art239-img03-570x316(es-es,MSDN.10).gif
Figura 3. Volver al texto.

Al igual que en la página anterior, incluimos un enlace a la página details.asp que llama al procedimiento almacenado CustOrdersDetails con el parámetro correspondiente. El código de la página es el siguiente:

<%@ Language=VBScript%>
<!-- #include file="conn.asp" -->
<%
Dim oId
oId = Request("oId")
Dim oRs, nReg
Set oRs = oConn.Execute("CustOrdersDetail(" + oId + ")",nReg,4)
%>
<html>
<body bgcolor="#E0EAFC">
<h3>Detalle de la orden <%=oId%></h3>
<table border=1 width=100% cellspacing="1" cellpadding="2">
<tr>
<th>Producto</th>
<th>Precio unitario</th>
<th>Cantidad</th>
<th>Descuento</th>
<th>Precio Total</th>
</tr>
<% Do While Not oRS.EOF %>
<tr bgcolor="#FFFFFF">
<td><%=oRs(0)%></td>
<td align="right"><%=oRs(1)%></td>
<td align="right"><%=oRs(2)%></td>
<td align="right"><%=oRs(3)%>%</td>
<td align="right"><%=oRs(4)%></td>
</tr>
<%
oRs.MoveNext
Loop
oRs.Close
oConn.Close 
Set oRs = Nothing
Set oConn = Nothing
%>
</table>
<p>Registros: <%=nReg%></p>
<p><a href="javascript:history.back()">Página&nbsp;anterior</a></p>
</body>
</html>

Y el resultado de esta página es el que vemos en la Figura 4.

Bb972247.art239-img04-570x316(es-es,MSDN.10).gif
Figura 4. Volver al texto.

Hasta aquí se observa que con un poco de código ASP y código en nuestra base de datos, podemos realizar cualquier tipo de consulta y publicarla en la Web fácilmente. Si las sentencias SELECT escritas en nuestros procedimientos almacenados son optimizables, los tiempos de respuestas son excelentes.

 

Modificando los datos de las tablas

Aparte de consultar los datos de nuestras tablas, también podemos modificar e insertar datos en tablas de VFP. Sobre este punto se debe prestar mucha atención al realizar nuestras páginas ASP y nuestros procedimientos almacenados. Las páginas ASP deben ser seguras y debemos validar todos los datos ingresados, no solo para prevenir errores del usuario sino también para tener en cuenta datos ingresados con fines maliciosos. En los procedimientos almacenados también debemos validar los parámetros recibidos. En este artículo sólo veremos el caso de modificar los datos de los clientes, sin prestar mucha atención al punto anteriormente citado. Para realizar la página de edición de datos, primeramente agregamos una columna en la página customers.asp para enlazar la página editcustomer.asp. Solo debemos agregar el siguiente código a continuación de la última columna de la tabla:

<td><a href="/vfp/editcustomer.asp?cId=<%=oRs(0)%>">Editar</a></td>

Antes de crear las páginas para la edición y actualización de los datos, agregamos dos nuevos procedimientos almacenados a la base de datos Northwind:

PROCEDURE GetCustomer(tcCID)
SELECT CustomerId, CompanyName, ContactName, ContactTitle, ;
Address, City, REGION, PostalCode, Country, Phone, Fax ;
FROM Customers ;
WHERE CustomerId = tcCid ;
INTO CURSOR GetCustomer
RETURN SETRESULTSET("GetCustomer")
ENDPROC
 
PROCEDURE UpdateCustomer
LPARAMETERS tcCustomerid, tcCompanyName, tcContactName, ; 
tcContactTitle, tcAddress, tcCity, tcRegion, ;
tcPostalCode, tcCountry, tcPhone, tcFax
LOCAL lnErr
UPDATE Customers SET ;
Companyname = tcCompanyname, ;
Contactname = tcContactname, ;
Contacttitle = tcContacttitle, ;
Address = tcAddress, ;
City = tcCity, ;
Region = tcRegion, ;
Postalcode = tcPostalcode, ;
Country = tcCountry, ;
Phone = tcPhone, ;
Fax = tcFax ;
WHERE Customerid = tcCustomerid
lnErr = _TALLY
RETURN lnErr
ENDPROC 

La página editcustomer.asp llama al procedimiento almacenado GetCustomer y contiene un formulario con todos los campos del registro y un botón Grabar que invoca a la página updatecustomer.asp. El código de la página es el siguiente:

<%@ Language=VBScript %>
<!-- #include file="conn.asp" -->
<html>
<%
Dim oRs, nReg, cId
cId = Request("cId")
Set oRs = oConn.Execute("GetCustomer('" & cId & "')", nReg, 4)
%>
<body bgcolor="#E0EAFC">
<h3>Editar cliente <%=cId%> </h3>
<hr>
<form id="frmCust" name="frmCust" action="updatecustomer.asp" method="post">
<table width="100%" border="0" cellpadding="5" cellspacing="0">
<tr>
<td>Id Cliente</td>
<td><input name="CustomerId" size="10" value="<%=Trim(oRs(0))%>" 
readonly style="color: #FF0000"></td>
</tr>
<tr>
<td>Nombre Compañia</td>
<td><input name="CompanyName" size="40" value="<%=Trim(oRs(1))%>"></td>
</tr>
<tr>
<td>Nombre Contacto</td>
<td><input name="ContactName" size="40" value="<%=Trim(oRs(2))%>"></td>
</tr>
<tr>
<td>Título Contacto</td>
<td><input name="ContactTitle" size="40" value="<%=Trim(oRs(3))%>"></td>
</tr>
<tr>
<td>Domicilio</td>
<td><input name="Address" size="40" value="<%=Trim(oRs(4))%>"></td>
</tr>
<tr>
<td>Ciudad</td>
<td><input name="City" value=" <%=Trim(oRs(5))%>"></td>
</tr>
<tr>
<td>Región</td>
<td><input name="Region" value=" <%=Trim(oRs(6))%>"></td>
</tr>
<tr>
<td>Código postal</td>
<td><input name="PostalCode" size="10" value="<%=Trim(oRs(7))%>"></td>
</tr>
<tr>
<td>País</td>
<td><input name="Country" value="<%=Trim(oRs(8))%>"></td>
</tr>
<tr>
<td>Teléfono</td>
<td><input name="Phone" value="<%=Trim(oRs(9))%>"></td>
</tr>
<tr>
<td>Fax</td>
<td><input name="Fax" value="<%=Trim(oRs(10))%>"></td>
</tr>
<tr> 
<td></td>
<td>
<input type="submit" value="Grabar" name="cmdG">&nbsp;
<input type="button" value="Cancelar" name="cmdC" OnClick="history.back()"/>
</td>
</tr>
</table>
</form>
<script Language="VBScript">frmCust.CompanyName.Focus</script>
</body>
</html>

Al ejecutar la página nos retorna el registro a modificar, tal como lo muestra la Figura 5.

Bb972247.art239-img05-486x650(es-es,MSDN.10).gif
Figura 5. Volver al texto.

Una vez editados los datos, el botón Grabar llama a la página updatecustomer.asp, la cual invoca al procedimiento almacenado UpdateCustomer con todos los campos pasados como parámetros. El código para ello es el siguiente:

<%@ Language=VBScript %>
<!-- #include file="conn.asp" -->
<html>
<%
Dim cParams
cParams = "'" & Request("CustomerId") & "','" & Request("CompanyName") & "','" & _
Request("ContactName") & "','" & Request("ContactTitle") & "','" & _
Request("Address") & "','" & Request("City") & "','" & _
Request("Region") & "','" & Request("PostalCode") & "','" & _
Request("Country") & "','" & Request("Phone") & "','" & Request("Fax") & "'" 
Dim nReg, oRs
nReg = 0
oRs = oConn.Execute("UpdateCustomer(" & cParams & ")", nReg, 4)
%>
<body bgcolor="#E0EAFC">
<h3>Grabar cliente <%=Request("CustomerId")%></h3>
<hr>
<% If nReg > 0 Then %>
<h1>Los datos se grabaron correctamente</h1>
<% Else %>
<h1>Error al grabar los datos</h1>
<% End If %> 
<input type="button" value="Continuar" name="cmdC" OnClick="location.href='customers.asp'"/>
</body>
</html>

Si los datos se grabaron correctamente en la tabla, la página se visualiza como lo muestra la Figura 6.

Bb972247.art239-img06-486x315(es-es,MSDN.10).gif
Figura 6. Volver al texto.

Con este último ejemplo observamos que la modificación de los datos no es una tarea complicada de realizar. Solo se deberán crear las páginas ASP y los procedimientos almacenados para cada necesidad y tomar las precauciones descriptas anteriormente.

 

Para tener en cuenta

Cuando se instala Internet Information Server (IIS) en un servidor, éste crea el usuario IUSR_<Nombre_Servidor> para el acceso anónimo al sitio publicado. Para que todo funcione correctamente, este usuario deberá tener los privilegios necesarios para consultar y modificar la carpeta donde se encuentra nuestra base de datos.

Por defecto IIS controla la contraseña de este usuario, esto nos puede traer problemas si la base de datos se encuentra en otro servidor distinto al servidor donde está ubicado el sitio web. Para evitar esto debemos desmarcar la casilla de verificación Permitir que IIS controle la contraseña, tal como se muestra en la Figura 7.

Bb972247.art239-img07-371x178(es-es,MSDN.10).gif
Figura 7. Volver al texto.

Para llegar a la ventana de la Figura 7 debes acceder a las Propiedades del sitio Web, seleccionando la solapa Seguridad de directorio y oprimiendo el botón Modificar en Control de autentificación y acceso anónimo.

Este caso está documentado en la Base de Conocimientos de Microsoft: Accessing FoxPro Table in ASP Returns Error 80040e14.

 

Conclusión

Como comentamos al inicio de este artículo, ésta es una opción válida y muy fácil de implementar para publicar nuestros datos de Visual FoxPro en la Web. La complejidad y el alcance de la aplicación a desarrollar solo depende de nosotros y de nuestras necesidades. Para finalizar, deseo agradecer el apoyo y las ideas de Antonio Muñoz de Burgos, que mucho me ayudaron para elaborar el código de los ejemplos de este artículo.

Bb972247.luis_m_guayan(es-es,MSDN.10).gif

Luis María Guayán está radicado en Tucumán, Argentina. Comenzó a programar en el año 1990 con lenguajes xBase y actualmente desarrolla con Microsoft Visual FoxPro. Es cofundador y SysOp de PortalFox, el mayor portal para desarrolladores en Visual FoxPro de habla hispana. Desde Febrero de 2002 es Microsoft MVP en el área Visual Developer: Visual FoxPro.