Array
(
)

Violação de chave primaria - PARADOX EM REDE

Hviana
   - 27 dez 2005

tenho um sistema Paradox em que vários usuários utilizam a mesma tabela simutaneamente...jah configurei minha BDE corretamente e controlo o Id do novo registro no evento AfterIsert da tabela, porem estou temdo problema de Violação de chave primaria..alguem sabe oq pode ser???


procedure TDM.tMailAfterInsert(DataSet: TDataSet);
begin
dm.tAutInc.Close;
dm.tAutInc.TableName := ´MAIL.DB´;
dm.tAutInc.IndexFieldNames := ´IDEMAILREC´;
dm.tAutInc.Open;
dm.tAutInc.Last;
dm.tMailIDEMAILREC.AsInteger :=
dm.tAutInc.FieldValues [´IDEMAILREC´] + 1;
end;



obs.: minha config. da BDE: LOCAL SHARE = TRUE, NET DIR = J:\ (drive de rede compartilhado) fiz isso em todas as máquinas


Eixox
   - 27 dez 2005

O negócio é o seguinte:

Quando você está trabalhando com o sistema em rede, ainda mais o Piradox, não pode esquecer que você é responsável por controlar a concorrência nas tabelas. Assim sendo o que pude ver no seu código, a não ser que deva existir mais alguma coisa é simplesmente o seguinte:

Você tem uma tabela - E aqui você está redeclarando uma coisa sem necessidade que é o nome da tabela para uma outra tabela e definindo o índice. Depois de abrir a tabela, você salta para o último registro e tenta atribuir um valor para o campo sem colocá-lo em modo de edição.

Em primeiro lugar eu recomendaria o seguinte:
Não faça essa redeclaração de tabela.

Crie uma nova tabela que irá se responsabilizar em ceder o valor autoincrementado.

Por exemplo: Crie uma tabela chamada TaAutoIncMail.Db
Crie nela somente um campo chamado CONTADOR e defina-o como Integer - Ele será a chave primária da tabela também, pois só existirá esse campo na tabela.

Agora coloque essa tabela no seu Data Module e defina a []upropriedade Exclusive para True[/u].

No form principal de sua aplicação, crie a seguinte função:

function TFormPrincipal.IncrementaCampo(vNomeTab: TTable; vCampo: String): LongInt;
var
Parar : Boolean;
begin
Repeat
Parar := True;
try
vNomeTab.Active := True;
except
Parar := False;
end;
until Parar = True;

vNomeTab.Edit;
vNomeTab.FieldByName(vCampo).asInteger := vNomeTab.FieldByName(vCampo).AsInteger + 1;
Result := vNomeTab.FieldByName(vCampo).asInteger;
vNomeTab.Post;
vNomeTab.Active := False;
end;

Feito isso, você irá chamar esse evento ou antes de gravar ou após inserir. Eu prefiro usar esse procedimento sempre antes da gravação, assim eu nunca perco um valor.

Uso esse código faz tempo e foi repassado por um cara aqui do Clube do Delphi. É extremamente eficiente.