hido yazdı:Merhaba;
İki tarih arasında kaç gün olduğunu buluyorum ve çıkan sayı kadar kayıdı databaseye kayıt ekliyorum;
Takıldığım nokta ise başlangıç tarihinden bitiş tarihine kadar kaç gün varsa, çıkan gün sayısı kadar her tarihi ayr, ayrı olarak nasıl ekleyebilirim databaseye kayıt oluştururum.
Kod: Tümünü seç
procedure TForm6.Button1Click(Sender: TObject);
var
TarihEkle: TDate;
J, Kacgun: Integer;
begin
Kacgun := DaysBetween(BaslangicTarihi.Date, BitisTarihi.Date);
begin
for J := 0 to Kacgun do
begin
TarihEkle := BaslangicTarihi.Date;
With TFDQuery.Create(Nil) do
begin
Connection := Connection;
Close;
SQL.Clear;
SQL.Add('Insert Into TARIHEGORE(TARIH)');
SQL.Add(' Values (TR');
ParamByName('TR').AsDate := TarihEkle;
ExecSQL;
TarihEkle := TarihEkle + 1;
end;
end;
end;
end;
Merhaba,
Örnek olarak gönderilen kod ile ilgili birkaç noktaya dikkat etmekte fayda var.
1- Bitiş Tarihi ile başlangıç tarihi kendi içinde kontrol edilmeli. Bitiş tarihi başlangıç tarihinden büyük ise işlem yapılmamalı.
2- TFDQuery.Create(nil) mutlaka Free() edilmeli. Yukarıdaki kod örneğinde hafıza kaçağı var. Döngü içinde tekrar tekrar nesne oluşturulduğu için hafıza kaçağı ciddi boyutlara ulaşabilir (bir yıllık veri oluşturulacak ise hafızada 365 adet TFDQuery temizlenmeden kalır).
Bunun anlaşılmasına yardımı olması için D2006 ve sonrası sürümlerde Proje kodunun ilk satırı olarak aşağıdaki ifadeyi yazmak *uygulama kapatıldığı zaman hafıza kaçağı olması halinde* bunu bir mesaj ile bildirir.
Kod: Tümünü seç
begin
ReportMemoryLeaksOnShutdown := True; // yazılması gereken satır
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm6, Form6);
Application.Run;
end.
Bunu sadece debug olarak derlenmiş EXE içinde istemeyebilirsiniz (Müşteriye teslim edilecek release olarak derlenmiş EXE'de olmasın istenilebilir). Bu durumda aşağıdaki şekilde eklenebilir:
Kod: Tümünü seç
begin
{$IFDEF DEBUG}
ReportMemoryLeaksOnShutdown := True; // yazılması gereken satır
{$ENDIF}
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm6, Form6);
Application.Run;
end.
3- Mümkün olduğunca "with" kullanmaktan kaçınmakta fayda var. Kodu karmaşıklaştırır.
4- TFDQuery.Create() ve SQL oluşturma komutları döngü dışında olmalı. Her döngü için yeniden nesne ve SQL komutu oluşturmaya gerek yok. SQL komutu aynı kullanılıyor.
5- Örnek olarak gönderilen SQL komutunda hata var.
Buradaki iki hata şunlar; (1) SQL komutu parametreleri önlerine ":" koyularak yazılmalıdır. (2) Parantez kapatılmamış. Bu iki hata compile edildiği zaman belli olmaz. Ancak çalışma zamanında ortaya çıkacaktır.
6- Özellikle birden fazla kez çalıştırılacak SQL komutlarını Prepare() ile database sunucuya bildirmekte fayda var. Database sunucu kendisini buna göre optimize ederek daha performanslı kayıt girişi sağlayacaktır.
7- ExecSQL() için Close() kullanılmasına gerek yok. ExecSQL() geriye veri çevirmez. Detaylı bilgi için:
http://stackoverflow.com/questions/2617 ... er.com/web
8- Programcının kendi seçimidir. Ancak bu gibi işlemleri bir fonksiyon/prosedür içine alıp buton tıklama olaylarına tek satırlık kodlar yazmak daha sonra kod içinde düzeltmeler yapar iken daha anlaşılır olacaktır.
Eğer aynı kod birden fazla yerde kullanılacak ise bunun yapılması daha fazla önerilir. Çünkü (a) gerek yok, (b) program bittiğinde EXE boyutu daha ufak olacaktır. Bunun da programın açılış süresinin kısalmasına faydası var.
9- Delphi tarafından verilen isimleri (Form6, Button1) olduğu gibi bırakmamakta fayda var. Ancak bu işlem örnek kod gönderme adına da yapılmış olabilir. Bu konuya dikkat çekmek adına belirtmek istedim.
Yukarıdaki noktalar göz önüne alındığı zaman aşağıdaki gibi bir kod yazılabilir. Kodu test etme imkanım olmadı. Düzeltilmesi gereken mantık hataları olabilir.
Kod: Tümünü seç
function TarihleriKaydet(const Baslangic, Bitis: TDate; const aConnection: TFDConnection): Boolean;
var
Tarih: TDate;
TempQuery: TFDQuery;
begin
Result := False;
if Bitis > Baslangic then Exit();
TempQuery := TFDQuery.Create(nil);
try
TempQuery.Connection := aConnection;
// SQL komutu değişmeyecek. Her döngü için terkar oluşturulmasına gerek yok.
TempQuery.SQL.Add('Insert Into TARIHEGORE(TARIH) Values(:TR)');
// Query birden fazla defa çalıştırılacak.
// Database tarafından optimizasyon için Prepare edilmesi gerekli
TempQuery.Prepare();
Tarih := Baslangic;
while Tarih <= Bitis do
begin
TempQuery.ParamByName('TR').AsDate := TarihEkle;
TempQuery.ExecSQL();
IncDay(Tarih); // Bir sonraki gün
end;
finally
// Programımızda hafıza kaçağı istemiyoruz.
TempQuery.Free();
end;
// Kayıt işlemi sırasında hata oluşmaz ise aşağıdaki kod çalıştırılır
Result := True;
end;
Bu fonksiyon oluşturulduktan sonra kullanımı aşağıdaki gibi olacaktır.
Kod: Tümünü seç
procedure TForm6.Button1Click(Sender: TObject);
begin
if not TarihleriKaydet(BaslangicTarihi.Date, BitisTarihi.Date, Connection) then
ShowMessage('Bitiş tarihi Başlangıç tarihinden büyük olamaz');
end;