Muy buen dia.
Soy nuevo en la comunidad y como todos me acerco a ustedes en busca de conocimiento, actualmente me encuentro desarrollando una aplicacion para la oficina misma que es utilza por al menos 5 usuarios de forma simultanea, estoy utilizando como base de datos MICROSOFT ACCES debido a que es la base que tienen instalados todos los quipos pero al momento de escribir de forma concurrente en la base esta se bloquea por el primer usuario que lo intenta.
he abierto el archivo de la base de datos directamente desde ACCES y escrito en el de forma simultanea en mas de un quipo, por lo que concluyo que el problema esta en mi forma de interactuar ACCES desde LAZARUS, enseguida les comparto un extracto del programa donde se pueden ver las interacciones que tengo con la base de datos y las configuracones generales:
-La conexion se realza mediante ODBC.
-Se inicializa el ODBCConn con un DSN de sistema que apunta al archivo .accdb.
-los componentes transaction y query tienen como DATABASE al ODBCConn.
-La propiedad Action del transaction tiene como parametro caCommit.
-El Query tiene inhabilitado el campo UsePrimaryKey.
Enseguida parte del codigo:
procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
ODBCConnection1.Connected:=False;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
ODBCConnection1.Connected:=True;
end;
//La siguiente funcion busca un ndice y s no exste lo registra.
Function TForm1.fncBDObtieneID(strTabla : String; strCampo : String; strValor : String) : Integer;
var
bolEncontrado : Boolean;
begin
fncBDObtieneID := -1;
While(fncBDObtieneID = -1) do
begin
SQLQuery1.SQL.Text := 'SELECT * FROM ' + strTabla + ' WHERE ' + strCampo + ' = :VALOR;';
SQLQuery1.Prepare;
SQLQuery1.Params.ParamByName('VALOR').AsString := strValor;
SQLQuery1.Open;
bolEncontrado := False;
while not SQLQuery1.Eof do
begin
If SQLQuery1.FieldByName(strCampo).AsString = strValor Then
begin
bolEncontrado := True;
fncBDObtieneID := SQLQuery1.FieldByName('ID').AsInteger;
end;
SQLQuery1.Next;
end;
SQLQuery1.Close;
SQLQuery1.Clear;
If Not bolEncontrado Then
begin
SQLQuery1.SQL.Text := 'INSERT INTO ' + strTabla + '(' + strCampo + ') VALUES(:VALOR);';
SQLQuery1.Prepare;
SQLQuery1.Params.ParamByName('VALOR').AsString := strValor;
SQLQuery1.ExecSQL;
SQLQuery1.Close;
end;
end;
end;
//
procedure TfrmPrincipalSHMC.btnCarrpsPruebasProcesarClick(Sender: TObject);
var
strTren : String;
lstDatosDeTren : TStringList;
intFor : Integer;
begin
lstDatosDeTren := TStringList.Create;
lstDatosDeTren.CommaText:=fncBuscaTrenQueSitue(tbxCarrosSituarEstacion.Text);
strTren := lstDatosDeTren.Strings[0] + ' ' + lstDatosDeTren.Strings[1];
If fncSituaListaConTren(strTren,lstDatosDeTren.Strings[2],tbxCarrosSituarEstacion.Text,tbxCarrosSituaZVP.Text,tblCarrosSituarUnidades) Then
begin
end;
for intFor := 0 To (tblCarrosSituarUnidades.RowCount -2) do begin
If (fncObtieneCodigoDeCarro(tblCarrosSituarUnidades.Cells[0,intFor + 1], tblCarrosSituarUnidades.Cells[1,intFor + 1]) = 'SC') Or (fncObtieneCodigoDeCarro(tblCarrosSituarUnidades.Cells[0,intFor + 1], tblCarrosSituarUnidades.Cells[1,intFor + 1]) = 'DT') Then
begin
tblCarrosSituarUnidades.Cells[2,intFor + 1] := 'OK';
intIDCarro := fncCarroObtieneID(tblCarrosSituarUnidades.Cells[0,intFor + 1] + tblCarrosSituarUnidades.Cells[1,intFor + 1]);
SQLQuery1.SQL.Text := 'INSERT INTO UCARROSSITUADOS(IDFUSUARIO, IDFCARRO) VALUES(:intUsuario, :intCarro);';
SQLQuery1.Prepare;
SQLQuery1.Params.ParamByName('intUsuario').AsInteger := intIDUsuario;
SQLQuery1.Params.ParamByName('intCarro').AsInteger := intIDCarro;
SQLQuery1.ExecSQL;
SQLQuery1.Close;
end
else
begin
tblCarrosSituarUnidades.Cells[2,intFor + 1] := 'ERROR';
end;
end;
end;
Las anteriores son las funciones con las que interactuo con la base de datos, les explico nuevamente el flujo de eventos que produce el bloqueo.
Usuario 1 inicia la aplicacion y ejecuta el evento click antes mencionado.
Usuario 2 ejecuta la aplicacon y ejecuta el evento click antes mencionado obteniendo como resultado un mensaje de error que indica que Usuario 1 tiene bloquada la base de datos.
Espero les sea de utilidad la informacion proporcionada y de ser necesario algo mas se los proporcionare con gusto.
Quedo en espera de sus amables respuestas
Acceso concurrente en acces con odbc
Comenzado por
csandoval
, feb 22 2019 04:16
Base de datos Acces Odbc Lazarus
1 respuesta en este tema
#1
Escrito 22 febrero 2019 - 04:16
#2
Escrito 13 abril 2019 - 01:24
Buenas espero que este ejemplo te pueda ayudar:
Con este codigo te presento el formulario completo para mejor guia
delphi
unit Unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, db, odbcconn, sqldb, Forms, Controls, Graphics, Dialogs, StdCtrls, ExtCtrls, DBGrids, ZConnection, ZDataset; type { TForm1 } TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; Button4: TButton; Button5: TButton; DS1: TDataSource; DBGrid1: TDBGrid; EditBuscar: TEdit; Editcodigo: TEdit; Editnombre: TEdit; Editdireccion: TEdit; GroupBox1: TGroupBox; Label1: TLabel; Label2: TLabel; Label3: TLabel; Panel1: TPanel; Conecion: TZConnection; Qry1: TZQuery; Qry1codigoid: TLongintField; Qry1direccion: TStringField; Qry1nombre: TStringField; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button4Click(Sender: TObject); procedure Button5Click(Sender: TObject); procedure DBGrid1DblClick(Sender: TObject); procedure FormShow(Sender: TObject); private procedure RefrescarDatos; procedure BusquedaRapida; public end; var Form1: TForm1; implementation {$R *.lfm} procedure TForm1.FormShow(Sender: TObject); begin RefrescarDatos; end; procedure TForm1.BusquedaRapida; begin If editBuscar.Text='' then begin MessageDlg('Escriba el Nombre que desea Buscar',mtInformation,[MbOK],0); editBuscar.SetFocus; end; Qry1.SQL.Clear; Qry1.SQL.Text := 'SELECT * FROM Empresa WHERE nombre ="&'+EditBuscar.text+'&"'; qry1.Open; end; procedure TForm1.Button1Click(Sender: TObject); begin if (editnombre.Text='')or (editdireccion.Text='')then begin MessageDlg('Los Campos no deben estar en Blanco',mtinformation,[mbok],0); exit end; qry1.SQL.Clear; qry1.SQL.Text:='INSERT INTO Empresa(nombre,direccion)VALUES(:B, :C)'; Qry1.Params[0].Value:=EditNombre.Text; Qry1.Params[1].Value:=EditDireccion.Text; qry1.ExecSQL; RefrescarDatos; ShowMessage('Datos Guardados Correctamente'); editnombre.SetFocus; end; procedure TForm1.Button2Click(Sender: TObject); begin if (editnombre.Text='')or (editdireccion.Text='')then begin MessageDlg('Los Campos no deben estar en Blanco',mtInformation,[mbok],0); exit end; Qry1.SQL.Clear; Qry1.SQL.Text:='UPDATE Empresa SET nombre=:B, direccion=:C WHERE codigoid=:A'; Qry1.Params[0].Value:=EditNombre.Text; Qry1.Params[1].Value:=Editdireccion.Text; Qry1.Params[2].Value:=EditCodigo.Text; Qry1.ExecSQL; RefrescarDatos; ShowMessage('Datos Modificados Correctamente'); editnombre.SetFocus; end; procedure TForm1.Button3Click(Sender: TObject); begin RefrescarDatos; end; procedure TForm1.Button4Click(Sender: TObject); begin if (editnombre.Text='')or (editdireccion.Text='')then begin MessageDlg('Los Campos no deben estar en Blanco',mtinformation,[mbok],0); exit end; qry1.SQL.Clear; Qry1.SQL.Text := 'DELETE FROM Empresa WHERE codigoid =:A'; Qry1.Params[0].Value:= EditCodigo.Text; qry1.ExecSQL; RefrescarDatos; ShowMessage('Dato Eliminado Correctamente'); editnombre.SetFocus; end; procedure TForm1.Button5Click(Sender: TObject); begin BusquedaRapida; end; procedure TForm1.DBGrid1DblClick(Sender: TObject); begin editCodigo.Text:=DBGrid1.DataSource.DataSet.FieldByName('codigoid').AsString; editNombre.Text:=DBGrid1.DataSource.DataSet.FieldByName('nombre').AsString; editdireccion.Text:=DBGrid1.DataSource.DataSet.FieldByName('direccion').AsString; end; Procedure TForm1.RefrescarDatos; begin Qry1.SQL.Clear; Qry1.SQL.Add('SELECT * FROM Empresa'); qry1.Open; editcodigo.Text:='Automatico'; editnombre.Text:=''; editdireccion.Text:=''; editBuscar.Text:=''; editnombre.SetFocus; end; end.
Con este codigo te presento el formulario completo para mejor guia