Firebird'de Transection yerine Generator'le UnicID üretme
Re: Delphi Firebird Transection ile ilgili bir soru
Merhaba.Benim programdada gelen, giden, numune kabul, fatura vs defterlerim var. ve hepsinin sizinki gibi tek ve sıralı gitmesi gerekiyordu. ayrı bir tabloda ben sayaçları saklıyorum. numara almak isteyen için kaydı post etmeden önce ilgili sayacı select ile okurken update with lock ile kilitleyerek okuyorum, sayacı ilerletip update ediyorum. ve commit ediyorum. eğer select ile okuyamazsam (kayıt başkası tarafından kilitli) kayıt kilidi kalkana kadar döngüye sokuyorum. bu işlem maksinum 1 sn. kadar kilitli bıraktığı için sayaç kaydını 50 kullanıcım var hiç takılma olmuyor.
Re: Delphi Firebird Transection ile ilgili bir soru
ben c++builder kullandığı için mantığı anlatacağım.
transaction başlatıyorum.
select sayac from sayaclar where sayac='GELENEVRAK' for update with lock gibi bir sql cümlesi ile kaydı kilitlemiş oluyorum. (kaydı okumak isteyen diğer kullanıcılar select yapmaya çalıştıklarında hata alacaklar şu an. bu sql cümlesi bir try catch bloğunun içinde. diğer kullanıcılar kaydı kilitleyenin bu kayıt ile işi bitene kadar beklesin diye sonsuz döngüde.)
sayacı 1 arttırıyorum. update sayaclar set sayac= :s where sayac='GELENEVRAK' ile güncelleyip taransaction'u commit veya commitretaining ile güncellediğimde kilit serbest kalıyor.
niye insertten önce yapmadığım sorusuna gelince. Sizde aynı sorunla karşılaşacaksınız. ya kullanıcı kaydı bir şekilde iptal ederse, kaydetmekten vazgeçerse, veya işlemler sırasında bir hata olursa. bende arada tek boş, atlanmış bir numara dahi olmaması gerekiyor. Önce kayıt yapılıyor ve numara sonra şef onayı vs. ile alınıyor. insert sonrası yaparsam benim yapımda açıklıklar kalabiliyordu.
transaction başlatıyorum.
select sayac from sayaclar where sayac='GELENEVRAK' for update with lock gibi bir sql cümlesi ile kaydı kilitlemiş oluyorum. (kaydı okumak isteyen diğer kullanıcılar select yapmaya çalıştıklarında hata alacaklar şu an. bu sql cümlesi bir try catch bloğunun içinde. diğer kullanıcılar kaydı kilitleyenin bu kayıt ile işi bitene kadar beklesin diye sonsuz döngüde.)
sayacı 1 arttırıyorum. update sayaclar set sayac= :s where sayac='GELENEVRAK' ile güncelleyip taransaction'u commit veya commitretaining ile güncellediğimde kilit serbest kalıyor.
niye insertten önce yapmadığım sorusuna gelince. Sizde aynı sorunla karşılaşacaksınız. ya kullanıcı kaydı bir şekilde iptal ederse, kaydetmekten vazgeçerse, veya işlemler sırasında bir hata olursa. bende arada tek boş, atlanmış bir numara dahi olmaması gerekiyor. Önce kayıt yapılıyor ve numara sonra şef onayı vs. ile alınıyor. insert sonrası yaparsam benim yapımda açıklıklar kalabiliyordu.
Re: Delphi Firebird Transection ile ilgili bir soru
Buyrun buda source.
niye fastscript kullanılmış. bazen istenilen formatta numara üretebilmek için.
niye fastscript kullanılmış. bazen istenilen formatta numara üretebilmek için.
Kod: Tümünü seç
int __fastcall TDM::Numara_Al(TpFIBQuery *Q, AnsiString Sayac,bool Oz,AnsiString OzelKod)
{
int S;
AnsiString Format;
dongu:
try
{
Q->SQL->Clear();
Q->SQL->Add("Select SAYAC,FORMAT from SAYACLAR Where ADI='"+Sayac+"'");
Q->SQL->Add("for Update with lock");
Q->ExecQuery();
}
catch(...)
{
goto dongu;
}
if(Q->RecordCount==1)
{
S=Q->FieldByName("SAYAC")->AsInteger;
Format=Q->FieldByName("FORMAT")->AsString;
try
{
Q->Close();
Q->SQL->Clear();
Q->SQL->Add("Update SAYACLAR Set SAYAC="+IntToStr(S+1)+" Where ADI='"+Sayac+"'");
Q->ExecQuery();
Q->Close();
}
catch(...)
{
goto dongu;
}
if(Oz && !Format.IsEmpty())
{
TfsScript *fs;
AnsiString Result;
fs=new TfsScript(this);
fs->Parent = fsGlobalUnit();
fs->Clear();
fs->AddVariable("SAYAC","Integer",S);
fs->AddVariable("Result","String",Result);
fs->Variables["SAYAC"]=S+1;
fs->Lines->Clear();
fs->Lines->Add("begin");
//ShowMessage(Format);
fs->Lines->Add(" Result:="+Format);
fs->Lines->Add("end.");
if(fs->Compile())
{
fs->Execute();
OzelKod=fs->Variables["Result"];
//ShowMessage(OzelKod);
}
delete fs;
}
return S+1;
}
return 0;
}
Re: Delphi Firebird Transection ile ilgili bir soru
ne demek zahmet. büyük bir zevkle. sağ olsunlar bana da gruptaki bir çok arkadaşın çok büyük yardımları oldu.
ben generatorleri benim uygulamamda sayı verme işi çok düzenli olmak zorunda olduğu için kullanmamıştım.
ben generatorleri benim uygulamamda sayı verme işi çok düzenli olmak zorunda olduğu için kullanmamıştım.
Re: Firebird'de Transection yerine Generator'le UnicID üretm
Selamlar,
Generator/Sequence'ler Transaction bağımsız çalışan nesnelerdir. Onlardaki handikap, sıralı gitmesi gereken bir şey olduğunda ve sizin Commit işiniz başarılı bir şekilde sonuçlanmaz ise, sıra numaralarında atlamalarla karşılaşırsınız. Bunu aklınızdan çıkarmayın.
Commit Retaining ile ilgili bir şeyler okumuşsunuz, benim başıma hiç gelmedi (ki Firebird 1.0 çıktığından beri kullanırım, daha öncesinde de Interbase kullanıyordum) bir sıkıntı oluşmadı.
Ben bu tür Identity almayla alakalı bir şey yaptığımda uyguladığım bir metod var onu anlatayım.
Bir tane Stored Procedure hazırlıyorum, bu stored procedure'e parametre veriyorum geriye de Generator değerini döndürüyorum. Post etmeden önce Identity field için stored procedure'ü çağırıp değeri alıyorum, kaydıma işleyip POST ve COMMITRETAINING yapıyorum.
Ama Foreign Keyi olan Master Detail olan tablolar için bu şekilde olmaz, çünkü masterın mutlak surette Identity alanının dolu olması ve önce onun post edilip Commit edilmesi gerekir. Aksi halde Foreign Key engeller.
Bu Generatorlerin değerlerini İlgili tablonun Triggerlarında da verebilirsiniz ama o zaman da Program ile Database arasında Refresh filan etmeniz gerekir (ID Değerlerin programa yansıyabilmesi için)
Generator/Sequence'lerdeki oluşan boşlukları nasıl önleyebilirim diye düşünüyorsanız, o zaman bir sayaç tablosu yapıp, işlemleri manuel olarak sizin takip etmeniz gerekir. Bu oluşacak boşlukları engellemede daha rahat ve kolay olur, oluşan boşlukları da kendiniz müdahale edip doldurabilirsiniz. Ama onun da şöyle bir sıkıntısı var, aynı sayaç için numara kaydı isteyenlere nasıl çiftlemeden yanıt vereceksiniz? Onu da biraz düşünerek sizler bulabilirsiniz, bu kadar da hazır lop olmasın değil mi!
Kolay Gelsin
Adnan
Generator/Sequence'ler Transaction bağımsız çalışan nesnelerdir. Onlardaki handikap, sıralı gitmesi gereken bir şey olduğunda ve sizin Commit işiniz başarılı bir şekilde sonuçlanmaz ise, sıra numaralarında atlamalarla karşılaşırsınız. Bunu aklınızdan çıkarmayın.
Commit Retaining ile ilgili bir şeyler okumuşsunuz, benim başıma hiç gelmedi (ki Firebird 1.0 çıktığından beri kullanırım, daha öncesinde de Interbase kullanıyordum) bir sıkıntı oluşmadı.
Ben bu tür Identity almayla alakalı bir şey yaptığımda uyguladığım bir metod var onu anlatayım.
Bir tane Stored Procedure hazırlıyorum, bu stored procedure'e parametre veriyorum geriye de Generator değerini döndürüyorum. Post etmeden önce Identity field için stored procedure'ü çağırıp değeri alıyorum, kaydıma işleyip POST ve COMMITRETAINING yapıyorum.
Ama Foreign Keyi olan Master Detail olan tablolar için bu şekilde olmaz, çünkü masterın mutlak surette Identity alanının dolu olması ve önce onun post edilip Commit edilmesi gerekir. Aksi halde Foreign Key engeller.
Bu Generatorlerin değerlerini İlgili tablonun Triggerlarında da verebilirsiniz ama o zaman da Program ile Database arasında Refresh filan etmeniz gerekir (ID Değerlerin programa yansıyabilmesi için)
Generator/Sequence'lerdeki oluşan boşlukları nasıl önleyebilirim diye düşünüyorsanız, o zaman bir sayaç tablosu yapıp, işlemleri manuel olarak sizin takip etmeniz gerekir. Bu oluşacak boşlukları engellemede daha rahat ve kolay olur, oluşan boşlukları da kendiniz müdahale edip doldurabilirsiniz. Ama onun da şöyle bir sıkıntısı var, aynı sayaç için numara kaydı isteyenlere nasıl çiftlemeden yanıt vereceksiniz? Onu da biraz düşünerek sizler bulabilirsiniz, bu kadar da hazır lop olmasın değil mi!

Kolay Gelsin
Adnan
Kuri Yalnız Jedi
Harbi Özgürlük İçin Pisi http://www.pisilinux.org/
Harbi Özgürlük İçin Pisi http://www.pisilinux.org/