Utilizamos cookies propias y de terceros. [Más información sobre las cookies].
Política de cookies
Proyecto AjpdSoft

· Inicio
· Buscar
· Contactar
· Cookies
· Descargas
· Foros
· Historia
· Nosotros
· Temas
· Top 10
· Trucos
· Tutoriales
· Wiki

Programación: Realizar aplicación en Delphi con tablas Paradox en Red
Delphi


Os explicamos en este artículo cómo realizar una aplicación en Borland Delphi 6 que utilice como motor de base de datos BDE (Borland Database Engine) y Paradox. Os explicamos cómo configurar adecuadamente el BDE y la propia aplicación para admitir conexiones de varios equipos de la red a estas tablas de forma simultánea (concurrente).



Una aclaración inicial sobre Paradox en red

Por definición, Paradox es una base de datos de escritorio, semejante a Microsoft Access, no está diseñada para soportar multitud de conexiones de red de varios usuarios, aunque con lo que os explicaremos a continuación será posible que varios equipos de la red accedan a las mismas tablas Paradox. Hemos de decir que en determinadas circunstancias, sobre todo si no se siguen los pasos al pie de la letra, se pueden corromper los índices, aunque esto no sería un problema grabe pues se pueden volver a regenerar.

Para aplicaciones de gestión de las que necesitéis varios usuarios conectados a la vez a las mismas tablas recomendamos utilizar otros motores de bases de datos profesionales, más preparados para soportar cientos y miles de usuarios concurrentes, incluso conexiones a través de Internet. Por ejemplo MySQL, que además de soportar lo que os comentamos, es un motor de base de datos gratuito.

Aunque si no hay más remedio, por el motivo que sea, os explicaremos cómo realizar una aplicación en Borland Delphi 6 que utilice Paradox y permita conexión de varios usuarios en red a las mismas tablas.

Preparar una aplicación Delphi para Paradox en red (múltiples usuarios conectados a las mismas tablas)

Para realizar aplicaciones que utilicen tablas Paradox en red debemos seguir los siguientes pasos:

Añadiremos un DataModule a nuestra aplicación desde el menú "File" - "New" - "Data Module", a este DataModule le añadiremos los siguientes componentes:

  • Session: con las siguientes propiedades:
    • Active: False.
    • AutoSessionName: False.
    • KeepConnection: False.
    • Name: Session1.
    • NetFileDir: vacío, se modificará en tiempo de ejecución.
    • PrivateDir: vacío, se modificará en tiempo de ejecución.
    • SessionName: S1.
    • SQLHourGlass: True.
    • Tag: 0.

Realizar aplicación en Delphi con tablas Paradox en Red - Session

  • Database: con las siguientes propiedades:
    • AliasName: vacío.
    • Connected: False.
    • DatabaseName: ap
    • DriverName: STANDARD.
    • Exclusive: False.
    • HandleShared: False.
    • KeepConnection: False.
    • LoginPrompt: False.
    • Name: db.
    • ReadOnly: False.
    • SessionName: S1.
    • Tag: 0.
    • TransIsolation: tiReadCommitted.

Realizar aplicación en Delphi con tablas Paradox en Red - Database

  • Table: con las propiedades importantes:
    • Active: False.
    • DatabaseName: ap.
    • Name: Table1.
    • SessionName: S1.
    • TableName: datos.db (tabla de paradox que deberá existir en el directorio o carpeta de datos, donde queramos guardar las tablas de la aplicación)

Realizar aplicación en Delphi con tablas Paradox en Red - Table

  • Datasource: con las propiedades:
    • AutoEdit: False.
    • DataSet: Table1.
    • Enabled: True.
    • Name: DataSource1.

Realizar aplicación en Delphi con tablas Paradox en Red - Datasource

Quedará algo así:

Realizar aplicación en Delphi con tablas Paradox en Red - Data Module

El Data Module (al cual le hemos puesto en la propiedad "Name" "MDatos") tendrá el siguiente código fuente:

unit UnidadModuloDatos;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Db, DBTables, inifiles, DBIProcs;

type
  TMDatos = class(TDataModule)
    db: TDatabase;
    Session1: TSession;
    Table1: TTable;
    Table1Id: TAutoIncField;
    Table1No: TStringField;
    Table1Si: TDateField;
    DataSource1: TDataSource;
    procedure AbrirBD(pw : String);
    procedure DataModuleCreate(Sender: TObject);
    procedure Table1AfterPost(DataSet: TDataSet);
  private
    { Private declarations }
  public
    hacer : boolean;
    { Public declarations }
  end;

var
  MDatos: TMDatos;

implementation

{$R *.DFM}


procedure TMDatos.AbrirBD(pw : String);
var
  ruta, rutaprivate, rutanet : string;
begin
  with tinifile.create (changefileext(paramstr(0),'.INI')) do
  try
    ruta := readstring ('Datos', 'Ruta', '');
    rutanet := readstring ('Datos', 'Ruta net', '');
    rutaprivate := readstring ('Datos', 'Ruta PrivateDir', '');
  finally
    free;
  end;

  With Session1 do
  begin
    AddPassword (pw);
  End;

  With db do
  begin
    Params.Clear;
    Params.Add('PATH=' + RUTA);
    Params.Add('DEFAULT DRIVER=PARADOX');
    Params.Add('ENABLE BCD=FALSE');
    Connected := true;
  End;
  table1.Active := True;

  {session1.NetFileDir := rutanet;
  session1.PrivateDir := 'C:\TEMP';
  Session1.Active := true;
  with db do
  begin
    Params.Clear;
    Params.Add('PATH=' + ruta);
    Params.Add('DEFAULT DRIVER=PARADOX');
    Params.Add('ENABLE BCD=FALSE');
    Connected := true;
  end;
  table1.active := true;  }
end;


procedure TMDatos.DataModuleCreate(Sender: TObject);
var
  ruta, servidor, rutaprivate, rutanet : string;
begin
  with tinifile.create (changefileext(paramstr(0),'.INI')) do
  try
    ruta := readstring ('Datos', 'Ruta', '');
    rutanet := readstring ('Datos', 'Ruta net', '');
    rutaprivate := readstring ('Datos', 'Ruta PrivateDir', '');
    servidor := readstring ('Datos', 'Es el servidor', '0');
    if ruta = '' then
    begin
      while not (ruta <> '') do
        ruta := InputBox ('Ruta de los datos...',
            'Introduzca la ruta de los ficheros *.db',
            'c:\p\datos ó \\a\PRed\datos');
      writestring ('Datos', 'Ruta', ruta);
    end;
    if rutaprivate = '' then
    begin
      while not (rutaprivate <> '') do
        rutaprivate := InputBox ('Ruta de los *.lck...',
            'Introduzca el PrivateDir (ruta de los ficheros *.lck)',
            'c:\p\temp');
      try
        CreateDir(rutaprivate)
      except
      end;
      writestring ('Datos', 'Ruta PrivateDir', rutaprivate);
    end;
    if rutanet = '' then
    begin
      while not (rutanet <> '') do
        rutanet := InputBox ('Ruta net...',
            'Introduce la Ruta de la carpeta NET',
            '\\a\PRed\datos\net');
     writestring ('Datos', 'Ruta net', rutanet);
    END; 
    if servidor = '' then
    begin
      while not (servidor <> '') do
        servidor := InputBox ('Servidor...',
            '¿Es este equipo el servidor?',
            'no/sí');
     if (UpperCase(servidor) = 'YES') or (UpperCase(servidor) = 'SÍ') or
       (UpperCase(servidor) = 'SI') then
       writestring ('Datos', 'Es el servidor', '1')
     else
       writestring ('Datos', 'Es el servidor', '0');
    end;
  finally
  end;

  With mdatos.Session1 do
  begin
    NetFileDir := RUTANET;
    PrivateDir := rutaprivate;
  End;
  With db do
  begin
    Params.Clear;
    Params.Add('PATH=' + RUTA);
    Params.Add('DEFAULT DRIVER=PARADOX');
    Params.Add('ENABLE BCD=FALSE');

    //No testeado si esto funciona
    //si no funciona por código habrá que hacerlo manual
    //en la configuración del BDE
    if uppercase (servidor) <> 'NO' then
      Params.Add('LOCAL SHARE=TRUE')
    else
      Params.Add('LOCAL SHARE=FALSE');

    Connected := true;
  End;
  table1.active := true;
end;

procedure TMDatos.Table1AfterPost(DataSet: TDataSet);
begin
 Table1.FlushBuffers;
end;

end.

 Explicamos brevemente (pues es bastante sencillo) lo que hace el código anterior:
  • Procedimiento AbrirBD: cuando sea llamado obtendrá los datos de conexión del fichero INI (configuración), configurará el componente Session (Session1) y el Database (db) con los valores leídos del fichero INI y abrirá las tablas de la aplicación.
  • Procedimiento DataModuleCreate: este procedimiento se ejecutará una sola vez al abrir la aplicación, realizará las siguientes tareas:
    • En primer lugar leerá los datos del fichero .ini de configuración de la aplicación (si existe):
      • Leerá la "Ruta" carpeta donde estén alojados los ficheros de datos de la aplicación (las tablas Paradox, ficheros con extensión .db y los índices). Será conveniente que esta ruta esté en notación UNC (Universal Naming Convection) del tipo: \\nombre_servidor\recurso_compartido\Carpeta_Datos
        • nombre_servidor: nombre de red (hostname) o IP del equipo que será el servidor, el que contenga la información (tablas paradox y demás).
        • recurso_compartido: nombre de la carpeta que hemos de compartir, la que tendrá los datos de la aplicación.
        • Carpeta_Datos: carpeta que crearemos dentro de la carpeta recurso_compartido para guardar los datos de la aplicación (ficheros .db e índices de Paradox).
      • Leerá la "Ruta net" que será la carpeta donde se guardará el fichero PDOXUSRS.NET (contiene información de bloqueos y otras funciones importantes para tablas compartidas), este fichero debe ser EL MISMO para todos los equipos que accedan a la aplicación, por lo que debe estar en el servidor, en una carpeta compartida a la que todos los usuarios tengan acceso. Este valor del fichero INI ("Ruta net") debe tener una notación UNC (Universal Naming Convection) del tipo:

      \\nombre_servidor\recurso_compartido\Carpeta_Net

      Donde:

      • nombre_servidor: nombre de red (hostname) o IP del equipo que será el servidor, el que contenga la información (tablas paradox y demás).
      • recurso_compartido: nombre de la carpeta que hemos de compartir, la que tendrá los datos de la aplicación.
      • Carpeta_Net: carpeta que crearemos dentro de la carpeta recurso_compartido para guardar el fichero PDOXUSRS.NET

      De esta forma, en todos los equipos configuraremos la misma ruta para el fichero PDOXUSRS.NET y será el mismo para todos.

      • Leerá la "Ruta PrivateDir" que será la carpeta donde el BDE guarde archivos temporales del usuario actual (del tipo "Del1.MB" y ficheros *.lck de bloqueo de tablas), por lo que debe ser una ruta LOCAL (no de red) que sea única para cada equipo, por ejemplo: C:\Temp\Aplicacion_Paradox_Red
      • También comprobará si el equipo actual es el servidor (valor "1") o es un equipo cliente (valor "0").
    • Si no existe alguno de los datos anteriores la aplicación mostrará una ventana pidiéndolos. En una aplicación comercial final es recomendable utilizar una ventana de configuración para todos estos datos, queda bastante más profesional que pedirlos uno a uno un InputBox.
    • Configura los distintos componentes con los datos obtenidos.
  • Para el caso del evento AfterPost del componente Table1, ejecutamos la función FlushBuffers que "fuerza" al BDE a guardar los cambios realizados en una tabla que hayan quedado en la caché, de esta forma se evitan incongruencias en los datos si varios usuarios han accedido a la misma tabla a la vez.

A continuación creamos un TForm que será el formulario principal de la aplicación, el que el usuario verá al iniciarla, donde estarán los datos de las tablas Paradox. En este formulario pondremos un TDBNavigator, TDBGrid, TListBox y un TButton, quedará de la siguiente forma:

Realizar aplicación en Delphi con tablas Paradox en Red - Formulario principal

 

 

El formulario tendrá el siguiente código:

unit UnidadPrincipal;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  DBTables, BDE,Db, Grids, DBGrids, ExtCtrls, DBCtrls, StdCtrls, inifiles,
  Buttons, shellapi;

type
  TFormPrincipal = class(TForm)
    DBNavigator1: TDBNavigator;
    Panel1: TPanel;
    Panel2: TPanel;
    Panel3: TPanel;
    ListBox1: TListBox;
    DBGrid1: TDBGrid;
    Splitter1: TSplitter;
    Panel4: TPanel;
    Image1: TImage;
    Panel5: TPanel;
    BInfo: TBitBtn;
    Panel6: TPanel;
    LWEB: TLabel;
    procedure BInfoClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure LWEBClick(Sender: TObject);
    procedure LWEBClick2(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  FormPrincipal: TFormPrincipal;

implementation

uses UnidadModuloDatos;



{$R *.DFM}

procedure TFormPrincipal.BInfoClick(Sender: TObject);
VAR
  TmpCursor: hDbiCur;
  rslt: dbiResult;
  UsrDesc: USERDesc;

begin
  LISTBOX1.Items.Clear;
  LISTBOX1.Items.add('Usuarios conectados:');
  Check(DbiOpenUserList(TmpCursor));
  try
    repeat
      Rslt := DbiGetNextRecord(TmpCursor, dbiNOLOCK, @UsrDesc, nil);
      if Rslt <> DBIERR_EOF then
      begin
        LISTBOX1.Items.add(UsrDesc.szUserName);
      end;
    until Rslt <> DBIERR_NONE;
  finally
    Check(DbiCloseCursor(TmpCursor));
  end;
  LISTBOX1.Items.add('------+++------');
  LISTBOX1.Items.add('Ruta fichero NET: ' +
      mdatos.Session1.NetFileDir);
  LISTBOX1.Items.add('Ruta directorio privado (*.lck): ' +
      mdatos.Session1.PrivateDir);
  LISTBOX1.Items.add('Ruta directorio datos: ' +
      mdatos.Session1.Databases[0].Directory);
  LISTBOX1.Items.add('Nombre del DRIVER: ' +
      mdatos.Session1.Databases[0].DriverName);
  LISTBOX1.Items.add('Nombre del Alias del database: ' +
      mdatos.Session1.Databases[0].GetNamePath);
end;

procedure TFormPrincipal.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
  mdatos.Session1.Close;
  mdatos.db.CloseDataSets;
end;

procedure TFormPrincipal.LWEBClick(Sender: TObject);
begin
  ShellExecute(Handle, Nil, PChar('http://www.ajpdsoft.com'),
      Nil, Nil, SW_SHOWNORMAL);
end;

procedure TFormPrincipal.LWEBClick2(Sender: TObject);
begin
  ShellExecute(Handle, Nil, PChar('http://www.ajpdsoft.com'),
      Nil, Nil, SW_SHOWNORMAL);
end;

end.

En realidad sólo es necesario código fuente si queremos hacer alguna acción "fuera de lo normal", Delphi ya incluye componetes como el DBNavigator con botones para añadir, eliminar, refrescar, mover al primero, último, siguiente anterior, etc. que no necesitan código fuente, es suficiente con enlazar el DBNavigator con el DataSource correspondiente. El código fuente anterior sólo lo usamos para mostrar información de la base de datos (como los usuarios que hay conectados) en un ListBox, si no mostrásemos esto no haría falta código fuente.

Para el caso del fichero principal del proyecto o aplicación Delphi (el .dpr) tendrá el siguiente código:

program P;

uses
  Forms,
  UnidadPrincipal in 'UnidadPrincipal.pas' {FormPrincipal},
  UnidadModuloDatos in 'UnidadModuloDatos.pas' {MDatos: TDataModule};

{$R *.RES}

begin
  Application.Initialize;
  Application.Title := 'AjpdSoft - Paradox en red/Paradox int Net';
  Application.CreateForm(TMDatos, MDatos);
  Application.CreateForm(TFormPrincipal, FormPrincipal);
  Application.Run;
end.

Que se creará de forma automática al ir agregando los formularios y módulos de datos, sólo tendremos que modificarlo si queremos realizar alguna comprobación o tarea antes de iniciar algún formulario.

Con lo anterior ya tendremos la aplicación preparada para ser ejecutada por varios usuarios (varios equipos) en la misma red utilizando las mismas tablas paradox.

La aplicación en funcionamiento:

Realizar aplicación en Delphi con tablas Paradox en Red - Aplicación en funcionamiento

 

Instalación y configuración del BDE

Lógicamente tendremos que instalar el BDE (Borland Database Engine) en todos los equipos donde queramos utilizar la aplicación que accederá a tablas Paradox. Lógicamente también todos los equipos deben estar conectados por red al servidor.

Tras instalar el BDE, deberemos configurarlo accediendo a "Inicio" - "Configuración" - "Panel de control", abriremos "BDE Administrator":

Realizar aplicación en Delphi con tablas Paradox en Red - BDE

Accederemos a la pestaña “Configuration”, seleccionaremos “System”, abriremos “INIT” y en la pestaña “Definition” cambiaremos el valor de la propiedad: “LOCAL SHARE” a False para el caso de los equipos clientes y True para el servidor. Es fundamental cambiar este valor en todos los equipos para que no haya problemas de corrupción de índices y demás:

Realizar aplicación en Delphi con tablas Paradox en Red - Configuración BDE

Compartir la carpeta de datos en el servidor para acceso de los clientes

En el equipo servidor, el que contendrá las tablas Paradox de la aplicación, debemos compartir la carpeta donde se encuentren dichas tablas, con permisos de lectura y escritura para los usuarios de los equipos cliente. Por ejemplo, si la carpeta de la aplicación está en:

C:\AjpdSoft Paradox en Red

Realizar aplicación en Delphi con tablas Paradox en Red - Carpeta de datos del servidor

Pulsaremos con el botón derecho sobre la carpeta, en el menú emergente seleccionaremos "Compartir y seguridad". En la ventana de propiedades de la carpeta, en la pestaña "Compartir", marcaremos la opción "Compartir esta carpeta", en "Recurso compartido" introduciremos el nombre que tendrá la carpeta compartida, por ejemplo "paradoxred" (es recomendable no utilizar espacios ni nombres muy largos):

Realizar aplicación en Delphi con tablas Paradox en Red - Compartir carpeta

Nota: si utilizamos Windows 2000, 2003 ó 2008 o si tenemos la seguridad avanzada activada en Windows XP deberemos darle permisos a los usuarios que se conectarán, estos usuarios deberán estar dados de alta en el equipo servidor con el mismo nombre de usuario y la misma contraseña que tengan en los equipos cliente, para que se establezca relación de confianza.

Tras compartir la carpeta, si el equipo servidor se llama "pcservidor" ya podremos acceder a la carpeta compartida desde cualquier PC poniendo (en "Inicio" - "Ejecutar"):

\\pcservidor\paradoxred

En la carpeta

C:\AjpdSoft Paradox en Red

Crearemos las subcarpetas:

  • "Datos": que contendrá las tablas Paradox de la aplicación:

Realizar aplicación en Delphi con tablas Paradox en Red - Compartir carpeta

  • "Net": será la carpeta donde se guardará el fichero PDOXUSRS.NET. Puesto que este fichero debe ser el mismo para todos los equipos (tanto el servidor como los clientes), cuando la aplicación pida la ruta "Net" introduciremos:

    \\pcservidor\paradoxred\Net

  • "temp": carpeta donde se guardarán los ficheros temporales, esta carpeta será local para cada equipo. En ella se guardarán los ficheros .lck, .MB, etc.

Nota importante: la carpeta temporal (PrivateDir) donde se alojarán los .lck no debe coincidir con la carpeta de los datos (tablas paradox). 

 

Contenido del fichero de configuración INI en el equipo servidor y en los clientes

El fichero de configuración de la aplicación será diferente para el equipo servidor y para los equipos cliente.

Para el equipo servidor será algo así:

[Datos]
Ruta=\\pcservidor\paradoxred\Datos
Ruta PrivateDir=C:\AjpdSoft Paradox en Red\temp
Ruta net=\\pcservidor\paradoxred\Net
Es el servidor=1

En los equipos clientes:

[Datos]
Ruta=\\pcservidor\paradoxred\Datos
Ruta PrivateDir=C:\AjpdSoft Paradox en Red\temp
Ruta net=\\pcservidor\paradoxred\Net
Es el servidor=0

 

Nota importante: como se puede observar en el ejemplo la ruta del NET DIR se debe poner tanto en el servidor como en el cliente con la notación UNC (Ej. \\MiServidor\misDatos\net), ambos deben tener el NET DIR escrito así. Lo mismo ocurre con la ruta de la carpeta de los datos.

 

Artículos relacionados

 

Créditos

Artículo realizado íntegramente por Alonsojpd miembro fundador del proyecto AjpdSoft.


Anuncios


Enviado el Sábado, 23 mayo a las 02:24:07 por ajpdsoft
Visita nuestro nuevo sitio web con programas y contenidos actualizados: Proyecto A