20 de julio de 2022

Cómo consumir datos de Visual FoxPro en sistemas de 64 bits utilizando un servidor vinculado

Cómo consumir datos de Visual FoxPro en sistemas de 64 bits utilizando un servidor vinculado

Autor: Carlos Alejandro Perez (QEPD) 1965-2021 (Chaco, Argentina)

Publicado en: http://logica10mobile.blogspot.com/2012/05/como-consumir-datos-de-visual-foxpro-en.html

Carlos Alejandro Perez



Introducción

Nos hemos puesto un poco nostálgicos, así que acá volcamos nuestra experiencia reciente en integrar datos de Visual Foxpro (32 bits) en un entorno de IIS de 64 bits, que no podía reducirse a correr 32 bits por condiciones de borde de la instalación.
Como es sabido, los sistemas operativos han ido migrando lentamente hacia los 64 bits. Entre otras ventajas, se tiene mayor direccionamiento en memoria RAM, y un rendimiento más sólido en los entornos de 64 bits, y lo más importante, el foco en los esfuerzos de las grandes compañías, entre otras ventajas. La migración de 16 a 32 bits demoró casi una década, pero de 32 a 64 está ocurriendo muy rápidamente.
En esta coyuntura, la realidad es que todavía existen muchos sistemas desarrollados en torno a Visual Foxpro, que es una aplicación de 32 bits. Éste puede correr en sistemas operativos Windows de 64 bits bajo la emulación WoW64 (Windows on Windows 64), que es esencialmente un conjunto de tres bibliotecas de enlace dinámico. Estas se encargan de colocar una capa muy liviana de adaptación en el sistema de 64 bits, a fin de traducir las llamadas y las estructuras de los sistemas de 32 bits, sin que éstos sufran modificación alguna. Sin embargo, por diseño, los manejadores de dispositivos se manejan de forma distinta. De esta forma, si por ejemplo tenemos una placa de video de tal marca y modelo, y la queremos usar en un sistema de 64 bits, deberemos indefectiblemente conseguir el driver de 64 bits. Como toda máquina virtual, es sumamente difícil comunicarse fuera de ella. En otras palabras, los drivers de 32 bits se podrán ver sólo dentro del ámbito Wow64, es decir: en un sistema operativo de 64 bits, los drivers de 32 serán visibles para los procesos emulados de 32 bits, pero no lo serán desde fuera de ese ámbito.
Ahora, ¿qué tiene que ver esto con Visual FoxPro? Bueno, fundamentalmente, las estrategias de acceso a datos que corren en Windows son basadas en el modelo ODBC (Open Database Connectivity). ODBC, en la implementación para Windows, no es otra cosa que un manejador de impresora modificado para bases de datos, es decir, funciona y se gestiona de manera muy parecida a un device-driver de impresora, y por lo tanto, pueden coexistir drivers de 32 y 64 en un sistema, pero sólo serán visibles dentro de sus ámbitos respectivos de ejecución. El rol del driver ODBC es análogo al manejador de impresora: así como un controlador de una determinada impresora “entiende” el lenguaje y los comandos de la misma (sean ésos PCL, Postcript, etc.), del mismo modo un manejador ODBC “entiende” las particularidades de una determinada base de datos. Y con OLEDB pasa más o menos lo mismo, recordemos que OLE DB es un derivado de ODBC, que introduce el modelo de objetos COM a ODBC, y copia su modelo de doble búfer, etc., con lo cual hay mucha similitud conceptual en cuanto al driver en sí (y no tanta similitud en cómo expone los datos hacia el cliente).

Escenarios posibles entre cliente y servidor

Suponiendo que tenemos un ejecutable de una aplicación cliente que desea acceder a un servidor de datos. Las combinaciones posibles serían estas, siempre hablando de un sistema operativo de 64 bits:
ClienteServidorDriver de 32 bits instaladoDriver de 64 bits instalado
32 bits32 bitsVisible desde el cliente, conectable.Invisible desde el cliente, innecesario para conectarse
32 bits64 bitsVisible desde el cliente, conectable.Invisible desde el cliente, innecesario para conectarse.
64 bits32 bitsInvisible desde el cliente, no se puede conectar.Visible desde el cliente, conectable
64 bits64 bitsInvisible desde el cliente, no se puede conectarVisible desde el cliente, se puede conectar.
Luego, si de VFP y de SQL Server se tratase, podemos asumir como cliente a VFP, y como servidor a SQL Server, y el cuadro de arriba sería válido igualmente. Si nos preguntamos si un cliente de 64 bits podría conectarse a un servidor que corre en 32 bits, la respuesta es: si, en la medida que exista el driver del lado del cliente. Supongamos que existiera un VFP de 64 bits, y se corre una instancia de SQL Server de 32 bits. Como SQL Server es un “servicio de datos” que funciona un un protocolo binario (esto es, basado en sockets con tráfico bajo un modelo propietario) llamado TDS (Tabular Data Stream), tendremos que este servicio es independiente de la versión (32 o 64 bits) que lo produzca: el protocolo es inmutable entre dichas plataformas. Para que lo veamos mejor, un servidor IIS de 32 bits producirá el mismo HTML que uno de 64 bits, ya que el protocolo de comunicación HTTP y el formato del mensaje HTML es conceptualmente siempre el mismo (un documento de texto), independientemente de la plataforma que lo genere. Análogamente, es posible entonces conectarse desde un cliente de 32 a un servidor de 64, siempre y cuando exista el driver de 32 bits para dicho servicio.

Por ejemplo, si queremos gestionar desde un cliente de 64 bits la creación y el mantenimiento de un driver ODBC, sólo veremos los drivers de 64 bits. Hagamos la siguiente prueba: iniciemos el Panel de Control, vayamos a Herramientas administrativas, Configurar orígenes de datos (ODBC). Pidamos crear una nueva conexión de sistema (DSN de sistema), y veremos sólo los drivers de 64 bits que la PC tenga instalados en ese momento:

image
Fig. 1: drivers de 64 bits visibles desde un cliente de 64 bits (Panel de Control)


Ahora bien, sin cambiar de PC, tratemos de hacer lo mismo desde un cliente de 32 bits, por ejemplo, desde el mismo Visual FoxPro, creando una base de datos .DBC y generando una conexión desde allí.

image
Fig. 2: drivers de 32 bits visibles de un cliente de 32 bits (VFP)


Como se aprecia en la figura 2, la cantidad es mayor, y entre ellos , vemos el driver para Visual FoxPro instalado. Tanto en el cliente de 64 bits (Panel de control) como en el cliente de 32 (VFP) podremos gestionar, por ejemplo, la creación de una conexión a SQL Server (independientemente de si el servidor SQL corre en 32 o en 64), porque tenemos ambos drivers de cliente instalados en la PC. Pero no podremos gestionar una conexión a VFP desde un cliente de 64, porque no existe el driver.

El problema con ASP.NET, VS y Windows de 64 bits.

Ahora bien, desde Visual Studio 2010, ¿qué sucede?. Supongamos este escenario:
  • Sistema operativo Windows de 64 bits –> IIS de 64 bits, que contiene:
    • IDE de Visual Studio 2010 convencional, 32 bits, instalado con ajustes por defecto sobre el Windows anterior.
    • Visual FoxPro, 32 bits
    • OLE-DB para Visual FoxPro, 32 bits
El objetivo es construir una página ASP.NET que acceda a los datos de VFP en ese escenario.
El problema es el siguiente:
  • Al programar la aplicación ASP.NET en VS2010, se puede crear sin problemas una conexión VFPOLEDB, ya que el cliente (justamente la IDE de Visual Studio) y el driver OLE-DB son de 32 bits. Al depurar la aplicación ASP.NET, se podrán consumir los datos de VFP con mucha facilidad, por ejemplo, utilizando un control SQLDataSource desde la misma página.
  • Pero al publicar el sitio en IIS, se transfieren los ensamblados a un entorno de ejecución de 64 bits. Las páginas se ejecutan bajo una máquina virtual .NET, que es un proceso de 64 bits. Este CLR de .NET es “incapaz” de registrar el driver de 32 bits OLE-DB para acceder a VFP, y las páginas fallan en IIS dando un error de “dll no registrada”, la de OLE-DB justamente.
Entonces la pregunta es: ¿cómo publicamos una página ASP.NET en un servidor IIS montado en un Windows de 64 bits, que no puede tener compatibilidad de 32 bits por alguna razón, y que la vez consuma datos de Visual FoxPro?
No existe una respuesta fácil. Las posibilidades que exploramos son las siguientes:

Idea centralQué habría que hacerContras
Correr el sitio ASP.NET en IIS habilitado para 32 bits
  • Activar la compatibilidad de 32 bits en IIS de 64 bits, corriendo en una ventana de comandos la siguiente instrucción:


C:\>cscript %SYSTEMDRIVE%\inetpub\adminscripts\adsutil.vbs SET W3SVC/AppPools/Enable32bitAppOnWin64 true


Si bien se activa la compatibilidad de 32 bits en IIS, al mismo tiempo se inhabilitan las de 64 bits. Luego, deberíamos tener todos los sitios corriendo en IIS en modo de 32 bits, aunque el SO de 64 bits (estamos pagando por algo que no usamos).
Instalar dos IIS en el servidor, uno de 32 y otro de 64La segunda instalación de IIS correría en modo de compatibilidad de 32 bits, sólo afectando a las de 64 en esa instancia, y en la otra podremos correr el sitio en 64 bits. Las páginas que acceden a VFP , al estar publicadas en otro servidor, debería correr en otro port HTTP o bien resolver por nombre (porque tienen una misma IP pública) a nivel del IIS principal.No es posible. No se puede instalar dos IIS en un mismo servidor. Si es posible instalar un IIS + Apache, o bien dos instancias de Apache, pero necesitamos IIS para correr ASP.NET.
Implementar un servidor de automatización COM hecho en VFPCrear un objeto COM (servidor de automatización) con VFP, que reciba las consultas SQL de ASP.NET, y devuelva datasets ADO.NET utilizando el comando CursorToXML()No es posible. No se podrá enlazar el COM en el espacio de 64 de bits del IIS en producción.
Implementar un servicio web con VFP y publicarlo en el mismo IIS que publica las páginas ASP.NET.Utilizar el mismo objeto de automatización COM del punto anterior, pero publicarlo como servicio web en el mismo IIS que sirve el sitio principal.No es posible, el COM de VFP de 32 bits no se podrá enlazar al ISAPI de 64 bits.
Ídem anterior, pero publicar el web service de VFP en un servidor Apache de 32 bits.Instalar en paralelo al IIS un servidor Apache de 32 bits, y publicar el servicio web de VFP de 32 bits por allí. Las páginas principales ASP.NET en IIS de 64 bits consultarán al web service local para acceder a los datos VFPTeóricamente posible, pero complicado. Al tener dos HTTP servers bajo una misma IP, uno de los HTTP servers debe trabajar en otro port, o bien transferir el request HTTP por nombre de dominio en el IIS, derivando al Apache de 32 bits las llamadas al servicio web.
Intentar conseguir un driver de 64 bits.Conseguir un driver OLE-DB de 64 bits para VFP provisto por la empresa Sybase, que sirve para su ETL (extracción, transformación y carga).Licencia de Sybase. ¿Dónde se lo consigue sin tener ningún producto Sybase? ¿funciona standalone o necesita un software de Sybase?

La solución del Servidor vinculado (Linked Server)


Tras dos meses de mucho probar y cavilar, se llegó a la conclusión que la mejor solución sería no tocar la infraestructura de IIS 64 bits preexistente, y utilizar el servicio de “servidor encadenado” que tiene SQL Server. El truco consiste en instalar una instancia vacía de SQL Server Express de 32 bits y activar dentro de ella un servidor vinculado o encadenado (linked server), que oficie de enlace entre los datos de VFP y los clientes de 64 bits.

El servidor vinculado o encadenado es esencialmente una pasarela, es decir, una capa de transformación de mensajes. A continuación mostramos un diagrama de bloques conceptual, donde desde un gran sitio ASP.NET en Windows Server de 64 bits, con SQL Server de 64 bits, se accede a VFP del driver VFPOLEDB de 32 bits:


VFP linked server


Figura 3: esquema de bloques de la solución

Microsoft ha incluido, increíblemente podríamos decir, la capacidad de tener servidores encadenados dentro de la instancia Express. El servidor encadenado puede ser cualquiera que soporte un driver OLE-DB para dicha versión (32 o 64 bits). Así, si debemos conectarnos a VFP, deberemos usar VFPOLEDB, que es un driver de 32 bits, y por lo tanto, descargar e instalar la versión de 32 bits de SQL Server Express, descargar e instalar el driver OLE-DB para Visual FoxPro, y estaríamos listos para lograr el acceso desde las páginas ASP.NET corriendo desde un servidor de 64 bits.

Una vez que el servidor encadenado está definido, se puede acceder desde cualquier cliente que tenga un driver de acceso a SQL, sea éste de 32 o de 64 bits. En la figura, el servidor HTTP instalado es IIS7.x, de 64 bits, que aloja un CLR de 64. Dentro de esa máquina virtual CLR, el proveedor administrado ADO.NET para SQL Server será uno regular, nativo, no existirá ningún problema porque sólo se necesitará la visibilidad del servicio de datos. El proveedor administrado hace abstracción de la plataforma del servidor, porque sólo ve los servicios sin importarle los procesos que lo generan. De este modo, desde .NET y con esta solución, se tendrá acceso indistintamente a SQL Server regular, de producción, que puede ser de 64 bits (alternativa de la figura, donde se asume un SQL server prexistente de 64 bits para el sistema principal), y al mismo tiempo, a SQL Server Express de 32 bits que aloja el servidor encadenado, vacío sin tablas nativas.

Configurando el servidor encadenado para que tome el archivo .DBC de Visual FoxPro, se tendrá acceso a todas las tablas de la base de datos Visual Fox, como si estuviesen residiendo de alguna manera en la instancia SQL Server Express.

Configuración paso a paso

1. Descargar e instalar SQL Server Express de 32 bits en el servidor IIS, o bien en algún lugar de la red que sea visible. Luego, hay dar acceso al proceso de SQL Server a la carpeta que contiene las tablas y el contenedor de base de datos de VFP.

Yendo a la carpeta en cuestión, en el explorador de archivos, hacer clic con botón derecho sobre la que contiene las tablas y el contenedor DBC, y seleccionar Propiedades, luego seleccionar la ficha Seguridad. La cuenta que debemos habilitar para acceso no es ninguna de las consabidas Network Service, ni Local System, ni System, sino la denominada MSSQL$SQLEXPRESS, como se muestra en la figura de abajo. El no hacerlo impedirá que se pueda acceder a dicha base de datos.

image

2. Iniciar el administrador de SQL Server, y configurar un servidor encadenado. Para ello abrir el administrador, y hacer clic con botón derecho sobre la instancia correspondiente. Seleccionar el nodo Server Objects, y dentro de él, la opción Linked Servers

image
Fig. 4

3. Verificar drivers. Expandir dicho nodo, y se verá el listado de drivers disponibles en el ámbito de 32 bits. Debe estar visible la opción VFPOLEDB

image
fig. 5

4. Agregar un nuevo servidor vinculado. Hacer clic con botón derecho sobre el nodo Linked Servers para agregar un nuevo un servidor vinculado a los datos VFP. Aparece el siguiente cuadro de diálogo:

image
Fig. 6

Proveer los siguientes datos:

  • Nombre del servidor encadenado: especificar el nombre o etiqueta para el servidor encadenado. Por ejemplo, MIAPPVFP

  • Proveedor: seleccionar OLE DB para Visual FoxPro

  • Nombre del producto: se puede especificar un identificador del producto, en este caso colocar la misma que el nombre del servidor encadenado.

  • Origen de datos: especificar el archivo .DBC de bases de datos de VFP, con el camino completo al directorio. Por ejemplo, C:\MIAPPVFP\DATOS\datos1.dbc

  • Dejar todos los demás campos en blanco, y hacer clic en Aceptar. Asegurarnos que la pantalla de alta quede así:
image
Fig. 7

5. Probar con una nueva consulta. Conectarse a la instancia de SQL Server Express que aloja el servidor encadenado. Recordemos que al no tener bases de datos de usuario de SQL Server, no existirán más que las predeterminadas (master, etc.). Cuando hagamos una consulta al servidor encadenado MIAPPVFP de este ejemplo, no se trabaja contra ninguna base de datos nativa, sino contra la representación interna de la base de datos VFP. En otras palabras, MIAPPVFP es, al mismo tiempo, servidor y base de datos. Debido a esta particularidad, para hacer una selección SELECT a una tabla de VFP, tendremos dos formas de acceder:
  1. Trabajando directamente con el servidor encadenado, armando consultas en Transact-SQL (en la figura 3, el trazo en azul) desde cualquier cliente de datos administrado de .NET. Esta técnica envía strings de consultas a la base de datos SQL Server Express, y el servidor encadenado, a través de VFPOLEDB, realiza la traducción necesaria al dialecto de VFP. Por este motivo, desde ADO.NET no podremos enviar a ejecutar comandos y funciones propias de VFP, como por ejemplo, SELECT DTOS(fecha) AS fecha… , ya que DTOS() no es una función reconocida por T-SQL. El servidor encadenado recibe la petición en T-SQL , la traduce al SQL de Visual FoxPro, ejecuta la consulta, y al recibir la respuesta, acondiciona el conjunto de resultados como si fuese un resultado nativo de SQL Server para enviárselo al cliente que efectuó la petición de datos.

  2. Utilizando la primitiva OPENQUERY de SQL Server, que permite enviar por paso-a-través un string conteniendo comandos nativos de VFP. En este caso, el servidor encadenado pasa a través de sí mismo la consulta sin modificarla, y sólo se encarga de “adaptar” el resultado de respuesta como una respuesta regular de SQL-Server.
5.1 Prueba con sintaxis T-SQL de SQL Server

Para probar si todo funciona bien, escribamos una consulta sencilla sobre una tabla que sabemos preexistente en la DBC de VFP. Nótese la sintaxis de acceso a la tabla. Se utiliza la notación de cuatro segmentos siempre que se acceda de esta manera a un servidor encadenado. Sin embargo, como aquí se trata en realidad de una carpeta y un contenedor de tablas, no existe el concepto de esquema, etc. por lo que estas etiquetas se omiten, dejando solamente los puntos. De esta forma, si el servidor encadenado se llama MIAPPVFP, y la tabla es clientes.dbf, se referencia como FROM miappvfp…clientes (tres puntos), como se muestra en la siguiente figura:

image
fig. 8

5.2 Prueba de consulta con paso-a-través y OPENQUERY

Cuando sea necesario emitir una consulta que sólo puede resolverse a través de VFP, será necesario utilizar el pasfo-a-través. Para lograr esto, será necesario utilizar la función OPENQUERY, en el siguiente formato de consulta:

SELECT <lista de campos> FROM OPENQUERY(<servidor_vinculado>, <string de consulta nativa VFP>)

Donde el <servidor_vinculado> debe especificarse sin comillas, y la consulta VFP nativa debe estar como una constante de caracteres encerrada entre comillas simples:

SELECT nombre,sexo FROM OPENQUERY(miappvfp,’SELECT * FROM clientes’)

image
fig. 9

Con esto configurado, estaremos en condiciones de consumir los datos desde páginas ASP.NET que se publiquen en IIS de 64 bits, pudiendo aprovechar lo que ya sabemos de ADO.NET, etc.

Conexión desde una aplicación de .NET

Para conectarnos desde Visual Studio, el string de conexión a SQL Server es parecido al que usaríamos con tablas regulares, pero en este caso se omite el catálogo inicial o el nombre de base de datos. Por ejemplo:

Data Source=SERVPRINC\SQLEXPRESS;User ID=MiUsuario;Password=MiPassword

Una vez establecido este origen de datos, en nuestro proyecto podremos generar objetos de datos que accedan a la base contenedora de VFP a través del servidor vinculado. Por ejemplo, si utilizásemos el control sqlDataSource para las páginas ASP.NET, podríamos probar una consulta así

image
fig. 10

Donde el secreto está en configurar el datasource SqlDataSource1 de la siguiente manera:

String de conexión: Por ejemplo,  Data Source=SERVPRINC\SQLEXPRESS;User ID=MiUsuario;Password=MiPassword” reemplazando las credenciales por las correspondientes a nuestra instalación.

Comando SELECT: Al configurar el SqlDataSource1, el asistente nos preguntará cómo recuperar la base de datos. Nótese que no nos permite acceder a ninguna tabla ya que no hemos especificado una base de datos por defecto, y la única opción será especificar una consulta SQL. La opción de procedimiento almacenado no está disponible.

image  image
Fig. 11 y 12

Este comando SELECT debe especificarse con sintaxis T-SQL de SQL Server, no con el dialecto de Visual FoxPro. Nótese que hemos definido un parámetro de consulta en la consulta:

SELECT nombre,doc_nro FROM miappvfp…clientes WHERE doc_nro = @doc_nro

Ajuste del parámetro de la consulta: Como el control SqlDataSource1 acepta varias formas de cargar el parámetro antes de ejecutar la consulta, seleccionamos que lo tome del control del formulario txtDoc, que es el cuadro de texto donde el usuario especifica el número de documento a buscar, colocando esos datos en el asistente:

 image
Fig. 13

Prueba de la consulta:

En el siguiente paso del asistente probaremos la consulta. En nuestro caso, a los fines de verificación solamente, hemos creado varias entradas en la tabla (doc_nro no es clave primaria en este test) con un mismo documento, para ver si recupera correctamente:

image   image
Fig. 14 y 15

Aceptemos todo y el SqlDataSource1 quedará configurado.

Ajuste del control GridView: Para el gridview de la página sólo bastará hacer clic en su smarttag (el pequeño triángulo que aparece en la esquina superior derecha al seleccionar el control con el ratón), y elegir como origen de datos al recién configurado SqlDataSource1.

image
fig. 16

Al hacerlo, inmediatamente quedará configurada la visual del gridview. Podemos cambiar la visual del gridview utilizando la opción AutoFormat, etc. y cambiarle la cabecera a cada columna utilizando la opción Edit Columns. A efectos ilustrativos, vemos cómo cambiar la cabecera de la primera columna, de nombre (que trae de la tabla de datos VFP) a Nombre de cliente.

image
fig. 17

Prueba de la página:

Pulsamos F5 y aguardamos hasta que aparezca la página

image
fig. 18

Colocamos el numero de documento y pulsamos consultar. A los breves instantes tendremos la respuesta:

image
fig. 19

Donde los datos provienen de Visual Foxpro. También podríamos haber utilizado un dataset, etc.

Publicar la página en el servidor IIS de 64 bits.

La prueba de fuego será publicar la página al servidor IIS, de 64 bits. Una vez hecho esto, podremos verificarla para ver si funciona correctamente. Esta es una imagen de la misma página instalada en el servidor de producción:

image
fig. 20

Con lo cual, hemos podido publicar los datos de VFP en un entorno ASP.NET con IIS de 64 bits, consumiendo datos de VFP.

Algunos cuidados a tener

1. Campos de tipo fecha: Cuando se utilicen fechas como parámetros, la consulta utilizando sintaxis de T-SQL no es optimizada en el motor VFP si la columna de filtrado es de tipo fecha. Por algún motivo, OLEBD para VFP ejecuta una exploración secuencial completa de toda la tabla, dando como resultado un rendimiento de consulta sub-óptimo que puede llegar incluso a una decena de segundos, algo inaceptable para una página web. En este caso, si necesitamos optimizar la consulta por parámetros de fecha en la tabla de VFP, la única solución posible será utilizar OPENQUERY como se explica en el punto siguiente.

2. Funciones nativas de VFP. Al utilizar sintaxis T-SQL, no podremos enviar una consulta con funciones propias de VFP, por ejemplo, INSTR() o DTOS() no podrían incluirse en la consulta. Como vimos en el paso anterior, tampoco podríamos optimizar una consulta que se haga sobre fechas de VFP. Para estos casos, debermos utilizar OPENQUERY indefectiblemente, a fin de pasar sólo un string de consulta en dialecto VFP que será procesado desde el mismo motor de VFP, sin pasar por ningun proceso de traducción en el servidor encadenado.

Por ejemplo, supongamos que necesitamos optimizar una consulta por la columna de fecha llamada fechaVenta en una tabla llamada VENTAS debemos seguir estos pasos:
  • indexar la tabla de Visual Foxpro con la función DTOS, y hacer la consulta desde ASP.NET con dicha consulta. Suponiendo que la columna sea fechaVenta, debemos indexarla con INDEX ON DTOS(fechaVenta) TAG fV en Visual Foxpro.

  • en ASP.NET, configurar los parámetros para que coincidan con el patrón YYYYMMDD de VFP que devuelve la función DTOS(). Por ejemplo, si tenemos una variable dFecha as date en .NET, podremos obtener su string equivalente al colocar dim cFechaParam as string = dFecha.ToString(“yyyyMMdd”).

  • Armar la consulta en el SQLDataSource, SQLAdapter, etc. especificando que el SelectCommand sea el sigiuente: 
SELECT * FROM OPENQUERY( miappvfp, ‘SELECT fechaVenta, factura, cliente FROM ventas WHERE DTOS(fechaVenta) = ‘”+cFechaParam+”’)

3. Palabras clave en consulta. Si bien VFP nos deja emitir consultas con nombres de campo o tablas que coincidan con las palabras clave, como por ejemplo llegar al extremo de colocar “SELECT select FROM select”  y que ejecute correctamente en VFP, siempre que haya una tabla llamada SELECT con una columna con nombre SELECT, este tipo de consultas será rechazada por VFPOLEDB en el servidor encadenado, dando un error en en la instancia de traducción si utilizamos las consultas T-SQL. Incluso utilizando OPENQUERY, la consulta podría realizarse correctamente en VFP, pero al rearmar la tabla de resultados, VFPOLEDB dará un error y no se podrá obtener el dataset, etc. desde .NET. Por tanto, debemos asegurarnos que, tanto con consultas en T-SQL como con  las especificadas dentro de OPENQUERY, no se utilicen objetos de la base de datos que coincidan con palabras clave de T-SQL.

Conclusión


Con la facilidad de servidor vinculado (linked server) que tiene SQL Server Express, podremos hacer que los procesos de 64 bits consuman los datos de VFP a través de VFPOLEDB. El SQL Server Express no tiene costo, y el driver OLEDB para VFP es de descarga gratuita. Con esta solución, si bien se agrega una instancia más al servidor principal o a algún otro de la red, tenemos la ganancia es que no se debe alterar el mecanismo en .NET de acceso a los datos, porque seguirá siendo el driver nativo que siempre estará disponible, en sistemas de 32 o de 64 bits. Así, uno puede tener toda una instalación de un gran sistema ASP.NET en Windows Server de 64 bits, y aún así acceder a los datos de Visual FoxPro sin necesidad de alterar en nada la programación ni la instalación en producción del sitio.

5 de febrero de 2022

Números Arábigos a Romanos

? NUM2ROMANO(1980)

FUNCTION Num2Romano(tnNum)
  DIMENSION laNum(13),laRom(13)
  LOCAL lnI, lcRom

  laNum(1) = 1
  laNum(2) = 4
  laNum(3) = 5
  laNum(4) = 9
  laNum(5) = 10
  laNum(6) = 40
  laNum(7) = 50
  laNum(8) = 90
  laNum(9) = 100
  laNum(10) = 400
  laNum(11) = 500
  laNum(12) = 900
  laNum(13) = 1000

  laRom(1) = "I"
  laRom(2) = "IV"
  laRom(3) = "V"
  laRom(4) = "IX"
  laRom(5) = "X"
  laRom(6) = "XL"
  laRom(7) = "L"
  laRom(8) = "XC"
  laRom(9) = "C"
  laRom(10) = "CD"
  laRom(11) = "D"
  laRom(12) = "CM"
  laRom(13) = "M"

  lcRom = ""

  FOR lnI = 13 TO 1 STEP -1
    DO WHILE tnNum >= laNum(lnI)
      tnNum = tnNum - laNum(lnI)
      lcRom = lcRom + laRom(lnI)
    ENDDO
  ENDFOR
  RETURN lcRom
ENDFUNC

13 de enero de 2022

Edad de una persona

Una (de tantas) funciones para calcular la edad de una persona.

* Ejemplo:
? Edad(DATE(1998,06,03))

*-----------------------------------------------------
* FUNCTION Edad(tdNac, tdHoy)
*-----------------------------------------------------
* tdNac = Fecha de nacimiento
* tdHoy = Fecha a la cual se calcula la edad (Por defecto toma la fecha actual)
*-----------------------------------------------------
FUNCTION Edad(tdNac, tdHoy)
  IF EMPTY(tdHoy)
    tdHoy = DATE()
  ENDIF
  RETURN FLOOR((VAL(DTOC(tdHoy,1)) - VAL(DTOC(tdNac,1))) / 10000)
ENDFUNC
*-----------------------------------------------------

Cetin Basoz, Izmir, Turkey
Publicado en www.foxite.com

8 de enero de 2022

Función PUTFILE() como se escribió originariamente (no en mayúsculas)

Artículo original: PUTFILE function as originally typed (not in uppercase)
http://vfpimaging.blogspot.com/2021/01/putfile-function-as-originally-typed.html
Autor: Cesar Ch.
Traducido por: Google Translate


Como ya se ha discutido en Fox.Wikis: "VFP siempre ha sido un poco más gracioso con los casos de nombres de archivo. Más específicamente, no está documentado cómo funciona con el caso de nombres de archivo. Se traducirá los nombres de archivo a minúsculas en algunos casos, a mayúsculas en otros, y dejarlo igual en otros."

PUTFILE() está en esa lista de funciones extrañas, siempre devolviendo los nombres de archivo en MAYÚSCULAS. Así que aquí hay una pequeña función que he estado usando que devuelve el nombre de archivo elegido de la forma en que el usuario lo escribió.

Los parámetros y el uso son exactamente los mismos que los de la función PUTFILE() original de Visual FoxPro:

FUNCTION XPUTFILE(tcCustomText, tcFileName, tcFileExt)

  * Usage:
  * ? PUTFILE("Save file as...", "MyFile.PDF", "PDF;TXT;*")

  #DEFINE COMMDLOG_DEFAULT_FLAG   0x00080000
  #DEFINE COMMDLOG_RO       4
  #DEFINE COMMDLOG_MULTFILES     512

  LOCAL lcSetDefa
  m.lcSetDefa = SET("Default") + CURDIR()

  LOCAL loDlgForm AS "Form"
  m.loDlgForm = CREATEOBJECT("Form")
  m.loDlgForm.ADDOBJECT("oleObject1", "oleComDialObject")

  LOCAL loDlg
  m.loDlg = m.loDlgForm.OleObject1

  LOCAL lcFilter, lcFileExt, lnExtCount, N
  IF NOT EMPTY(tcFileExt)
    lnExtCount = GETWORDCOUNT(m.tcFileExt, ";")
    lcFilter = ""
    FOR N = 1 TO lnExtCount
      lcFileExt = GETWORDNUM(m.tcFileExt, N, ";")
      IF lcFileExt = "*"
        lcFilter = lcFilter + "All files|*.*"
      ELSE
        lcFilter = lcFilter + lcFileExt + " files|*." + lcFileExt && EVL(tcFileExt, "All files|*.*")
      ENDIF
      IF N < lnExtCount
        lcFilter = lcFilter + "|"
      ENDIF
    ENDFOR
  ELSE
    lcFilter = "*.*|*.*" && EVL(tcFileExt, "All files|*.*")
  ENDIF

  m.loDlg.FILTER    = lcFilter
  m.loDlg.FileName  = EVL(m.tcFileName, "")
  m.loDlg.DialogTitle  = EVL(m.tcCustomText, "Save file as...")
  m.loDlg.FLAGS    = COMMDLOG_RO + COMMDLOG_DEFAULT_FLAG
  m.loDlg.MaxFileSize  = 256

  LOCAL lnResult AS INTEGER, lcFileName
  * lnResult = loDlg.ShowOpen()
  m.lnResult = m.loDlg.ShowSave()

  * Restore the original directory
  SET DEFAULT TO (m.lcSetDefa)

  IF EMPTY(m.loDlg.FileTitle) && Clicked 'Cancel'
    m.lcFileName = ""
  ELSE
    m.lcFileName = m.loDlg.FileName
  ENDIF
  m.loDlgForm = NULL
  RETURN m.lcFileName


DEFINE CLASS oleComDialObject AS OLECONTROL
  OLECLASS ="MSComDlg.CommonDialog.1"
ENDDEFINE