Tarih adeti kadar kayıt ekleme - Çözüldü

Delphi'de kod yazma ile ilgili sorularınızı bu foruma yazabilirsiniz.
Cevapla
Kullanıcı avatarı
hido
Üye
Mesajlar: 268
Kayıt: 29 Mar 2014 04:32

Tarih adeti kadar kayıt ekleme - Çözüldü

Mesaj gönderen hido »

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;
En son hido tarafından 24 Ağu 2016 12:57 tarihinde düzenlendi, toplamda 1 kere düzenlendi.
Kullanıcı avatarı
yhackup
Üye
Mesajlar: 118
Kayıt: 09 Ağu 2014 09:09
İletişim:

Re: Tarih adeti kadar kayıt ekleme

Mesaj gönderen yhackup »

For döngüsü ile aradaki gün kadar dönüyor ya, her döngüde Date + i, yap ilk tarihi bir gün artırır.
Çaylak Delphici :D

Yakup ULUTAŞ
ertank
Kıdemli Üye
Mesajlar: 1716
Kayıt: 12 Eyl 2015 12:45

Re: Tarih adeti kadar kayıt ekleme

Mesaj gönderen ertank »

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.

Kod: Tümünü seç

SQL.Add(' Values (TR');
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;
Kullanıcı avatarı
yhackup
Üye
Mesajlar: 118
Kayıt: 09 Ağu 2014 09:09
İletişim:

Re: Tarih adeti kadar kayıt ekleme

Mesaj gönderen yhackup »

Süper anlatım, Feyz aldım.

Bende bir servisimde Tarihi bu şekilde geriye almışım,

Kod: Tümünü seç

Button3Click(Sender: TObject);
var
 intservis : AgencyServiceSoap;
 intBegin , intEnd : TXSDateTime;
 sonuc : MSUBaseResult;
 c: Cardinal;
begin
  try
   c := GetTickCount;
   intservis := GetAgencyServiceSoap(false , '' , HTTPRIO1);
   intBegin := TXSDateTime.Create;
   intEnd   := TXSDateTime.Create;
   intBegin.AsDateTime := Date -2;
   intEnd.AsDateTime   := Date;
   sonuc := intservis.GetAgencyProductions('88.249.90.69' , 'NYAZICI', 'x53V89C5' , intbegin , intEnd);
  finally
     ShowMessage('bitti ' + CurrToStr((GetTickCount - c) div 1000));
  end;
end;
Çaylak Delphici :D

Yakup ULUTAŞ
ertank
Kıdemli Üye
Mesajlar: 1716
Kayıt: 12 Eyl 2015 12:45

Re: Tarih adeti kadar kayıt ekleme

Mesaj gönderen ertank »

yhackup yazdı:Süper anlatım, Feyz aldım.

Bende bir servisimde Tarihi bu şekilde geriye almışım,

Kod: Tümünü seç

Button3Click(Sender: TObject);
var
 intservis : AgencyServiceSoap;
 intBegin , intEnd : TXSDateTime;
 sonuc : MSUBaseResult;
 c: Cardinal;
begin
  try
   c := GetTickCount;
   intservis := GetAgencyServiceSoap(false , '' , HTTPRIO1);
   intBegin := TXSDateTime.Create;
   intEnd   := TXSDateTime.Create;
   intBegin.AsDateTime := Date -2;
   intEnd.AsDateTime   := Date;
   sonuc := intservis.GetAgencyProductions('88.249.90.69' , 'NYAZICI', 'x53V89C5' , intbegin , intEnd);
  finally
     ShowMessage('bitti ' + CurrToStr((GetTickCount - c) div 1000));
  end;
end;
Merhaba,

Yukarıdaki kodda da hafıza kaçağı durumu var.
1- intBegin ve intEnd değişkenleri Create() edildiği halde Free() edilmemiş. Aşağıdaki şekilde kullanımı daha doğru olacaktır.
2- "Date - 2" ifadesi yerine DateUtils içindeki IncDay() fonksiyonunu kullanmak daha sağlıklı olacaktır.
3- Sonuc değerinin doğruluğunu kontrol etmekte fayda var.

Kod: Tümünü seç

Button3Click(Sender: TObject);
var
 intservis : AgencyServiceSoap;
 intBegin , intEnd : TXSDateTime;
 sonuc : MSUBaseResult;
 c: Cardinal;
begin
  try
    c := GetTickCount;
    intservis := GetAgencyServiceSoap(false , '' , HTTPRIO1);
    intBegin := TXSDateTime.Create();
    try
      intEnd   := TXSDateTime.Create();
      try
        intBegin.AsDateTime := IncDay(Date, -2);
        intEnd.AsDateTime   := Date;
        sonuc := intservis.GetAgencyProductions('88.249.90.69' , 'NYAZICI', 'x53V89C5' , intbegin , intEnd);
      finally
        intEnd.Free();
      end;
    finally
      intBegin.Free();
    end;
  finally
    ShowMessage('bitti ' + CurrToStr((GetTickCount - c) div 1000));
  end;
end;
Cevapla