Usuwanie rekordu w gridzie podłączonym pod Firebirda

0
Add('insert into lista (login, password)');
Add('values (:login, :password)');

ten kod dodaje nowy rekord w bazie danych, przynajmniej firebirdowej.

jaki kod należy napisać żeby po zaznaczeniu rekordu w gridzie i kliknięciu buttona zaznaczony rekord został usunięty ?

może coś w stylu:

Add('delete into lista (login, password)');
Add('values(:login, :password)');

Tylko to musi być pod buttonem i jak to połączyć z zaznaczonym rekordem w gridzie ?

Z góry dzięki za pomoc.

1

grid tylko wizualizuje dane zawarte w datesecie , musisz z datasetu wyciągnąć klucz wg którego chcesz usunąć wiersz z tabeli i pod buttona podpiąć akcję:

 delete from table where (tu odpowiedni warunek) 
0

Niech pytający poczyta dokumentację Firebirda, bo takie błędy wykazują brak podstaw...

Ale przechodząc do rzeczy. Szkoda, że nie napisałeś jakich komponentów używasz. Zatem zakładam, że to będzie coś w stylu TIBDataSet. Oczywiście wiadomo, że to są komponenty do Interbase i z nowszymi wersjami FB mogą nie działać. Osobiście sprawdziłem, że do wersji 2.5 działają idealnie. Ten komponent posiada przecież wbudowany generator http://docwiki.embarcadero.com/RADStudio/Seattle/en/IBUpdateSQL_and_IBDataSet_Editor_dialog_box zapytań:

  • ModifySQL
  • InsertSQL
  • DeleteSQL
  • RefreshSQL

Które się wykonują po wykonaniu metod:

  • Post (ModifySQL albo InsertSQL w zależności czy przedtem było Insert czy Edit)
  • Delete
  • Refresh

Zatem aby skasować dany rekord (zakładając że mam wygenerowane polecenie DeleteSQL) trzeba po prostu wykonać:

DataSet.Delete;
Transaction.Commit;

Commit po to aby zapisać zmiany do bazy.

0

wyciągnąć klucz id z bazy danych rozumiem, może coś w stylu current row get id ?

trudny orzech :D jak dla mnie , co by nie było połączenie 3 componentów bazy , grida i buttona

0
Renewerek napisał(a):

wyciągnąć klucz id z bazy danych rozumiem, może coś w stylu current row get id ?
Chodzi o to, że usuwasz po kluczu głównym. Tworząc tabelę w bazie zakładasz jakiś Primary Key i jego używasz do usuwania/modyfikacji danych. Zazwyczaj jest to sztuczny ID.

Renewerek napisał(a):

trudny orzech :D jak dla mnie , co by nie było połączenie 3 componentów bazy , grida i buttona
To jeszcze jest łatwe. Jakbyś napisał jakich komponentów używasz do łączenia było by prościej Ci pomóc.

0

masz grida podpiętego przez datasource do datasetu , musisz z tego datasetu wyciągnąć dane pozwalające na jednoznaczne powiązanie wiersza w tabeli 'datasdet' z wierszem w bazie i na podstawie tego zbudować komendę "delete" z odpowiednim warunkiem "where" , która usunie z tabeli żądany wiersz

1

Nie rozumiem... To co OP pisze, da się zrobić bez pisania ani jednej linii kodu (tak, tak - ani jednej linii. Jest do tego przeznaczony komponent TDBNavigator albo dedykowane akcje (mam na myśli TActionList i dodanie akcji z kategorii Dataset; są wszystkie podstawowe akcje do operowania na zbiorze danych); pod warunkiem, że zna się swoje środowisko w stopniu minimum). Włączając w to dodawanie, edycje i usuwanie danych. Jakieś "wyciąganie klucza", jakieś delete from tabela - PO CO?
W czym tu jest problem, bo nie rozumiem?

1

@wloochacz zgodzę się. Jednak aby zadziałała Twoja metoda DataSet musi mieć wygenerowane zapytanie DeleteSQL.

Dodatkowo DBNavigator jednak jest przestarzałym komponentem i w poważnych aplikacjach nie zobaczysz go. Poza tym nie robi nic więcej poza tym co ja zaproponowałem w swoim 1 poście:

procedure TDBNavigator.BtnClick(Index: TNavigateBtn);
begin
  if (DataSource <> nil) and (DataSource.State <> dsInactive) then
  begin
    if not (csDesigning in ComponentState) and Assigned(FBeforeAction) then
      FBeforeAction(Self, Index);
    with DataSource.DataSet do
    begin
      case Index of
        nbPrior: Prior;
        nbNext: Next;
        nbFirst: First;
        nbLast: Last;
        nbInsert: Insert;
        nbEdit: Edit;
        nbCancel: Cancel;
        nbPost: Post;
        nbRefresh: Refresh;
        nbDelete:
          if not FConfirmDelete or
            (MessageDlg(SDeleteRecordQuestion, mtConfirmation,
            mbOKCancel, 0) <> idCancel) then Delete;
      end;
    end;
  end;
  if not (csDesigning in ComponentState) and Assigned(FOnNavClick) then
    FOnNavClick(Self, Index);
end;

Jeśli program służy nauce jestem w stanie ścierpieć obecność DBNavigatora. Tak pisało się 20 lat temu...

0
Mr.YaHooo napisał(a):

@wloochacz zgodzę się. Jednak aby zadziałała Twoja metoda DataSet musi mieć wygenerowane zapytanie DeleteSQL.

Masz rację i nie masz racji...
Jeśli używasz starocia typu IBX - tak musisz.
Jeśli używasz FireDAC'a - nie musisz.

Tak naprawdę wiele zależy od użytych komponentów. Jedna mają bardziej "kumaty" generator SQL (chodzi o automatyczne generowane zapytania SQL dla aktualizacji danych, po ich zmianie na poziomie DataSetu) inne nie. Tym durnowatym trzeba pomóc (jak IBX właśnie) i należy czasami coś tam dopisać w Insert/Update/Delete SQL.
A żaby było jeszcze śmieszniej to w komponentach typu IBX najlepiej działa odpowiednik TTable. Ma sprytny generator SQL, który potrafi robić prawie wszystko automatycznie. Nie tylko edycję danych, ale też sortowanie i filtrowanie... Jeśli dobrze pamiętam, a mogę nie pamiętać - używałem tego na poważnie ponad 15 lat temu ;-)

Dodatkowo DBNavigator jednak jest przestarzałym komponentem i w poważnych aplikacjach nie zobaczysz go. Poza tym nie robi nic więcej poza tym co ja zaproponowałem w swoim 1 poście:

/ciach/

Jeśli program służy nauce jestem w stanie ścierpieć obecność DBNavigatora. Tak pisało się 20 lat temu...

I co z tego? Ten komponent robi to automatycznie i jest trywialny w użyciu.
A przecież o to pytającemu chodziło, prawda?
Poza tym pisałem też o akcjach - zauważyłeś?

Dla mnie to 20 lat temu pisało się tak jak pokazałeś; wpisanie SQL, użycie generatora do UpdateSQL, trzymanie tego w DFM a i pewnie komponentów typu TQuery/TIBDataSet w DataModule. To jest dla mnie coś, czego nie mogę ścierpieć.

I co z tego?
Wiem, że tak pisze 90% ludzi w Delphi. A niech sobie piszą na zdrowie.
A, że ja robię to zupełnie inaczej (i nie, nie używam intensywnie narzędzia typu ORM) to moja sprawa i mam swoje powody.
Natomiast nie chodzi o oto, że moja racja jest fajniejsza. Nie mam zamiaru nikogo do niczego przekonywać.

0
wloochacz napisał(a):

Jeśli używasz starocia typu IBX - tak musisz.
Jeśli używasz FireDAC'a - nie musisz.
Zatem zwracam honor. Akurat nie wiedziałem, że nie wszystkie komponenty wymagają generowania SQL'a design time.

wloochacz napisał(a):

Tak naprawdę wiele zależy od użytych komponentów. Jedna mają bardziej "kumaty" generator SQL (chodzi o automatyczne generowane zapytania SQL dla aktualizacji danych, po ich zmianie na poziomie DataSetu) inne nie. Tym durnowatym trzeba pomóc (jak IBX właśnie) i należy czasami coś tam dopisać w Insert/Update/Delete SQL.
Ogólnie to trzeba sobie przyznać, że IBX'y nie mają za dobrego parsera SQL'owego i przy bardziej skompilowanych joinach nie radzą sobie po prostu. Trzeba wtedy ręcznie poprawiać, bo np nie jest w stanie znaleźć tabeli której dotyczy update/insert/delete.

wloochacz napisał(a):

A żaby było jeszcze śmieszniej to w komponentach typu IBX najlepiej działa odpowiednik TTable. Ma sprytny generator SQL, który potrafi robić prawie wszystko automatycznie. Nie tylko edycję danych, ale też sortowanie i filtrowanie... Jeśli dobrze pamiętam, a mogę nie pamiętać - używałem tego na poważnie ponad 15 lat temu ;-)
Tylko za używanie TTable w komunikacji serwer-klient zakazywałbym pisania programów ;) No i nie jestem pewny, ale tu filtry wykonują się po stronie klienta? Jeśli tak to w ogóle porażka.

wloochacz napisał(a):

I co z tego? Ten komponent robi to automatycznie i jest trywialny w użyciu.
A przecież o to pytającemu chodziło, prawda?
Poza tym pisałem też o akcjach - zauważyłeś?
Tak zauważyłem. Jednak warto wiedzieć co się dzieje pod spodem. Mimo, że i tak dużą część roboty odwala IDE to warto wiedzieć jak z palca usunąć/zupdate'ować dany rekord.

wloochacz napisał(a):

Dla mnie to 20 lat temu pisało się tak jak pokazałeś; wpisanie SQL, użycie generatora do UpdateSQL, trzymanie tego w DFM a i pewnie komponentów typu TQuery/TIBDataSet w DataModule. To jest dla mnie coś, czego nie mogę ścierpieć.
Wiesz, generujesz tylko raz ewentualnie jak zmieniasz strukturę tabeli. Tylko nie wiem w czym Ci przeszkadza trzymanie komponentów w DataModule? Chcesz tworzyć wszystko runtime (), czy trzymać na formatkach? Akurat pytam na poważnie, bo sam mam czasem problem gdzie trzymać komponenty bazodanowe.

wloochacz napisał(a):

I co z tego?
Wiem, że tak pisze 90% ludzi w Delphi. A niech sobie piszą na zdrowie.
A, że ja robię to zupełnie inaczej (i nie, nie używam intensywnie narzędzia typu ORM) to moja sprawa i mam swoje powody.
Natomiast nie chodzi o oto, że moja racja jest fajniejsza. Nie mam zamiaru nikogo do niczego przekonywać.
Tak, jednak ja mam doświadczenie z różnymi stylami pisania takich aplikacji bazodanowych i w zasadzie nie widzę rozwiązania które by było idealne. Każde ma swoje wady, a niektóre mnie wręcz odrzucają jak trzymanie komponentów bazodanowych na formatkach.

1
Mr.YaHooo napisał(a):
wloochacz napisał(a):

A żaby było jeszcze śmieszniej to w komponentach typu IBX najlepiej działa odpowiednik TTable. Ma sprytny generator SQL, który potrafi robić prawie wszystko automatycznie. Nie tylko edycję danych, ale też sortowanie i filtrowanie... Jeśli dobrze pamiętam, a mogę nie pamiętać - używałem tego na poważnie ponad 15 lat temu ;-)
Tylko za używanie TTable w komunikacji serwer-klient zakazywałbym pisania programów ;) No i nie jestem pewny, ale tu filtry wykonują się po stronie klienta? Jeśli tak to w ogóle porażka.

To znaczy, że nie masz pojęcia jak to jest zrealizowane pod spodem (a twierdzisz, że "Jednak warto wiedzieć co się dzieje pod spodem." ) i powtarzasz stereotypy rodem z BDE.
A to nieprawda! O tym tez już tu pisałem i zostałem prawie zbanowany przez indolentów...
Sam poczytaj, zalecam dokładnie i ze zrozumieniem, czym naprawdę jest TFDTable w odniesieniu d relacyjnych baz danych na przykładzie FireDAC:
http://docwiki.embarcadero.com/RADStudio/XE8/en/Browsing_Tables_(FireDAC)
I nie, nie tylko w FireDAC są takie mechanizmy w oparciu o komponent typu Table.

O filtrowaniu/sortowaniu po stronie klienta już pisałem. I nie, nie jest to porażka. To zależy po prostu. Ale na pewno porażką będzie twierdzenie, że zawsze porażką jest sortowanie po stronie klienta lub serwera. To zależy...

Mr.YaHooo napisał(a):
wloochacz napisał(a):

I co z tego? Ten komponent robi to automatycznie i jest trywialny w użyciu.
A przecież o to pytającemu chodziło, prawda?
Poza tym pisałem też o akcjach - zauważyłeś?
Tak zauważyłem. Jednak warto wiedzieć co się dzieje pod spodem. Mimo, że i tak dużą część roboty odwala IDE to warto wiedzieć jak z palca usunąć/zupdate'ować dany rekord.

Tu nie ma o czym dyskutować, pełna zgoda.

Mr.YaHooo napisał(a):
wloochacz napisał(a):

Dla mnie to 20 lat temu pisało się tak jak pokazałeś; wpisanie SQL, użycie generatora do UpdateSQL, trzymanie tego w DFM a i pewnie komponentów typu TQuery/TIBDataSet w DataModule. To jest dla mnie coś, czego nie mogę ścierpieć.
Wiesz, generujesz tylko raz ewentualnie jak zmieniasz strukturę tabeli. Tylko nie wiem w czym Ci przeszkadza trzymanie komponentów w DataModule? Chcesz tworzyć wszystko runtime (), czy trzymać na formatkach? Akurat pytam na poważnie, bo sam mam czasem problem gdzie trzymać komponenty bazodanowe.

Nie trzymam niczego na formatkach, bo i nie mam formatek w IDE...
Wszystko jest generowane automatycznie w runtime. Layout formatek też, który później można sobie dostosować za pomocą drag'n'drop w aplikacji, a nie w IDE.
Nie trzymam żadnego komponentu typu query na formatce czy DataModule.
Wszystko trzymam w metadanych, system je konsumuje i tworzy co trzeba.

Po co mam trzymać ileś set czy tysięcy zapytań na DataModule? To ani nie jest wygodne rozwiązanie w pracy na co dzień...
Zwłaszcza, że mam tylko jedną instancję danego zapytania na DataModule i nie mogę łatwo pozyskać kolejnej. Mogę oczywiście skopiować komponent, poprawić co trzeba i już. A potem biedzić się przy drobnej zmianie struktury tabel w bazie...
A to bez sensu...
Wolę rozwiązanie na kształt fabryki. Potrzebuję jakichś danych, proszę o nie fabrykę. Ona się martwi skąd ma to pobrać i jak ma to przygotować. Ja oczekuję od niej gotowego i poprawnie skonfigurowanego Query.

Mr.YaHooo napisał(a):
wloochacz napisał(a):

I co z tego?
Wiem, że tak pisze 90% ludzi w Delphi. A niech sobie piszą na zdrowie.
A, że ja robię to zupełnie inaczej (i nie, nie używam intensywnie narzędzia typu ORM) to moja sprawa i mam swoje powody.
Natomiast nie chodzi o oto, że moja racja jest fajniejsza. Nie mam zamiaru nikogo do niczego przekonywać.
Tak, jednak ja mam doświadczenie z różnymi stylami pisania takich aplikacji bazodanowych i w zasadzie nie widzę rozwiązania które by było idealne. Każde ma swoje wady, a niektóre mnie wręcz odrzucają jak trzymanie komponentów bazodanowych na formatkach.

Ja robię to zupełnie inaczej, ale to nie jest rozwiązanie które da się opisać w dwóch zdaniach.
To może kod pokażę:

Aby utworzyć dwa zapytania master-detail piszę coś takiego:

    FboTppDeviceTool := TboTppDeviceTool.Create();
    FboTppDeviceTool.SQLParser.OrderBy.Clear;
    FboTppDeviceTool.SQLParser.Where.Clear.Add(FboTppDeviceTool.PKFields);
    FboTppDeviceTool.SQLParser.CommitSQL();

    FboTppToolOutput := TboTppToolOutput.Create(nil);
    FboTppToolOutput.RelationToMaster(FboTppDeviceTool);

Mam dwie instancje TFDQuery, połączone ze sobą. Nie ma ani grama kodu na DataModule. Nie łączę ręcznie datasetów.
Nie tworzę na etapie zapytania powiązań przez WHERE.
Robi się samo, ale trzeba było napisać sporo kodu pod spodem.
Za to jest wygodniej, szybciej i elastyczniej.

Dzięki w/w mechanizmom definiuję zapytania tylko na poziomie zbioru danych; określam SELECT bez warunków i sortowania. To co potrzebne w kontekście filtrów i sortowania załatwia automat lub można to wydziergać ręcznie, ale obiektowo (taki Builder dla WHERE).
Np. taki kod:

function TdDSController.IsUniqueFieldValue(AField: TField): Boolean;
var
  lDS, lFindDS: TDADQuery;
  lEntity     : TDEntity;
begin
  Result  := True;
  lDS     := AField.DataSet as TDAdQuery;
  lEntity := lDS.dFLEXConf.Entity;
  if Assigned(lEntity) then
  begin
    lFindDS := UpdateConnection.CreateQuery(lEntity.IDEntity, True);
    try
      lFindDS.SQLParser.OrderBy.Clear;
      lFindDS.SQLParser.Where.Clear.Add(AField.FieldName);
      lFindDS.SQLParser.CommitSQL([AField.Value], [AField.DataType]);
      lFindDS.SetFastForward(False, False, 1);
      lFindDS.OpenEx(AField.Value);
      Result := lFindDS.IsEmpty;
    finally
      lFindDS.Free;
    end;
  end;
end;

Potrafi sprawdzić czy wartość danego pola jest unikalna dla dowolnego zapytania.
Podkreślam - ten kod zadziała poprawnie dla każdego zapytania SELECT. Nie muszę tego rozpatrywać za każdym razem.

0
wloochacz napisał(a):

To znaczy, że nie masz pojęcia jak to jest zrealizowane pod spodem (a twierdzisz, że "Jednak warto wiedzieć co się dzieje pod spodem." ) i powtarzasz stereotypy rodem z BDE.
A to nieprawda! O tym tez już tu pisałem i zostałem prawie zbanowany przez indolentów...
Sam poczytaj, zalecam dokładnie i ze zrozumieniem, czym naprawdę jest TFDTable w odniesieniu d relacyjnych baz danych na przykładzie FireDAC:
http://docwiki.embarcadero.com/RADStudio/XE8/en/Browsing_Tables_(FireDAC)
I nie, nie tylko w FireDAC są takie mechanizmy w oparciu o komponent typu Table.
Akurat swoją wiedzę opieram na działaniu IBX'ów. Po prostu z nimi miałem najwięcej styczności. I tu niestety przy dużych tabelach działało to mułowato.

wloochacz napisał(a):

O filtrowaniu/sortowaniu po stronie klienta już pisałem. I nie, nie jest to porażka. To zależy po prostu. Ale na pewno porażką będzie twierdzenie, że zawsze porażką jest sortowanie po stronie klienta lub serwera. To zależy...
Faktycznie mogę przyznać rację, że to zależy. Jednak IMHO to jest cofnięcie się do czasów baz plikowych. Nie po to mam serwer żeby pobierać tysiące rekordów i je sobie filtrować. Takie pisanie pamiętają moi współpracownicy tworzący rozwiązanie w Clipperze i tu nigdy nie zmienię zdania ;)

Mr.YaHooo napisał(a):

Nie trzymam niczego na formatkach, bo i nie mam formatek w IDE...
Wszystko jest generowane automatycznie w runtime. Layout formatek też, który później można sobie dostosować za pomocą drag'n'drop w aplikacji, a nie w IDE.
Nie trzymam żadnego komponentu typu query na formatce czy DataModule.
Wszystko trzymam w metadanych, system je konsumuje i tworzy co trzeba.
W takim razie zazdroszczę kodu oraz całej architektury. O tym nie pomyślałem. Ja niestety muszę trzymać wszystkie formatki w projekcie. Przy dużych systemach projekty się rozrastają w dużym tempie.

wloochacz napisał(a):

Po co mam trzymać ileś set czy tysięcy zapytań na DataModule? To ani nie jest wygodne rozwiązanie w pracy na co dzień...
Zwłaszcza, że mam tylko jedną instancję danego zapytania na DataModule i nie mogę łatwo pozyskać kolejnej. Mogę oczywiście skopiować komponent, poprawić co trzeba i już. A potem biedzić się przy drobnej zmianie struktury tabel w bazie...
A to bez sensu...
Wolę rozwiązanie na kształt fabryki. Potrzebuję jakichś danych, proszę o nie fabrykę. Ona się martwi skąd ma to pobrać i jak ma to przygotować. Ja oczekuję od niej gotowego i poprawnie skonfigurowanego Query.
Ja mam z kolei podobne rozwiązanie. Z tym, że fabryka zwraca mi odpowiedniego DataModule. Taka namiastka obiektu odpowiadającego danej rzeczy(np. kontrahent czy dokument). To w niej zawarta jest cała logika aplikacji. Faktem jest, że czasem tych modułów robi się dużo. Nie mniej jednak dość wygodnie się tego używa, bo taki DataModule odpowiada np. dokumentowi wraz z jego pozycjami.

Mr.YaHooo napisał(a):

Ja robię to zupełnie inaczej, ale to nie jest rozwiązanie które da się opisać w dwóch zdaniach.
To może kod pokażę:

Aby utworzyć dwa zapytania master-detail piszę coś takiego:
CIACH

Mam dwie instancje TFDQuery, połączone ze sobą. Nie ma ani grama kodu na DataModule. Nie łączę ręcznie datasetów.
Nie tworzę na etapie zapytania powiązań przez WHERE.
Robi się samo, ale trzeba było napisać sporo kodu pod spodem.
Za to jest wygodniej, szybciej i elastyczniej.
Właśnie tu dla niektórych może tkwić problem. Dużo kodu pod spodem. Ja trafiłem do zespołu jak całe "core" systemu było już gotowe i napisane dawno temu. Mnie zaś przypadło się napisanie jednego z 2 największych modułów całej aplikacji. Nie było czasu na zmiany. Jednak jestem coraz bliżej tego aby zrefaktoryzować to porządnie. Jednak wiadomo potrzeba na to czasu.

wloochacz napisał(a):

Dzięki w/w mechanizmom definiuję zapytania tylko na poziomie zbioru danych; określam SELECT bez warunków i sortowania. To co potrzebne w kontekście filtrów i sortowania załatwia automat lub można to wydziergać ręcznie, ale obiektowo (taki Builder dla WHERE).
Np. taki kod:
CIACH
Potrafi sprawdzić czy wartość danego pola jest unikalna dla dowolnego zapytania.
Podkreślam - ten kod zadziała poprawnie dla każdego zapytania SELECT. Nie muszę tego rozpatrywać za każdym razem.
Bardzo fajne rozwiązanie. Widać, że ktoś to sensownie przemyślał i się opłaciło :)

0
Mr.YaHooo napisał(a):
wloochacz napisał(a):

To znaczy, że nie masz pojęcia jak to jest zrealizowane pod spodem (a twierdzisz, że "Jednak warto wiedzieć co się dzieje pod spodem." ) i powtarzasz stereotypy rodem z BDE.
A to nieprawda! O tym tez już tu pisałem i zostałem prawie zbanowany przez indolentów...
Sam poczytaj, zalecam dokładnie i ze zrozumieniem, czym naprawdę jest TFDTable w odniesieniu d relacyjnych baz danych na przykładzie FireDAC:
http://docwiki.embarcadero.com/RADStudio/XE8/en/Browsing_Tables_(FireDAC)
I nie, nie tylko w FireDAC są takie mechanizmy w oparciu o komponent typu Table.
Akurat swoją wiedzę opieram na działaniu IBX'ów. Po prostu z nimi miałem najwięcej styczności. I tu niestety przy dużych tabelach działało to mułowato.

Ponieważ IBXy nie posiadają odpowiednik Live Data Window znanego z FireDAC.
I to nie tylko z TIBTable działała "mułowato"; jak zassasz całą sporą tabelę do Qury, będzie działać tak samo mułowato...

Mr.YaHooo napisał(a):
wloochacz napisał(a):

O filtrowaniu/sortowaniu po stronie klienta już pisałem. I nie, nie jest to porażka. To zależy po prostu. Ale na pewno porażką będzie twierdzenie, że zawsze porażką jest sortowanie po stronie klienta lub serwera. To zależy...
Faktycznie mogę przyznać rację, że to zależy. Jednak IMHO to jest cofnięcie się do czasów baz plikowych. Nie po to mam serwer żeby pobierać tysiące rekordów i je sobie filtrować. Takie pisanie pamiętają moi współpracownicy tworzący rozwiązanie w Clipperze i tu nigdy nie zmienię zdania ;)

Eeehh.... o tym tez już pisałem...
To powtórzę pytanie; masz dane pochodzące z zapytania, które jest efektem długo działającej analizy danych i zwraca mało rekordów.
Niech odpalenie zapytanie trwa 3 minuty i zwraca 1K rekordów.
Ja to posortuje po stronie klienta i potrwa to 0,01 sekundy, Ty to posortujesz po stronie serwera i będzie to trwało 3 min.
Dalej uważasz, że nigdy nie zmienisz zdania?

Mr.YaHooo napisał(a):
Mr.YaHooo napisał(a):

Nie trzymam niczego na formatkach, bo i nie mam formatek w IDE...
Wszystko jest generowane automatycznie w runtime. Layout formatek też, który później można sobie dostosować za pomocą drag'n'drop w aplikacji, a nie w IDE.
Nie trzymam żadnego komponentu typu query na formatce czy DataModule.
Wszystko trzymam w metadanych, system je konsumuje i tworzy co trzeba.
W takim razie zazdroszczę kodu oraz całej architektury. O tym nie pomyślałem. Ja niestety muszę trzymać wszystkie formatki w projekcie. Przy dużych systemach projekty się rozrastają w dużym tempie.

Uważam, że klikanie formatek to zadanie dla małpy a nie dla programisty. Nienawidzę tego robić i dlatego tego nie robię.
Ale jest jeszcze potężna wartość dodana; specyfika mojego programu zakłada dostosowanie do warunków i wymagań konkretnego klienta.
Ja mogę zmienić układ każdego okna bez rekompilacji bezpośrednio u klienta (Panie, ja bym chciał aby tego nie było, a to było w innym miejscu a tu by przydało się widzieć to i tatmo).
Mogę też np. dodać do konkretnej formatki jakieś tam dane i wyświetlić je na danej formatce. Dane mogą pochodzić z mojego systemu lub nie. I też bez rekompilacji.
Jakbym miał to robić w sposób standardowy, to po 5 klientach umarł w butach...

Mr.YaHooo napisał(a):
wloochacz napisał(a):

Po co mam trzymać ileś set czy tysięcy zapytań na DataModule? To ani nie jest wygodne rozwiązanie w pracy na co dzień...
Zwłaszcza, że mam tylko jedną instancję danego zapytania na DataModule i nie mogę łatwo pozyskać kolejnej. Mogę oczywiście skopiować komponent, poprawić co trzeba i już. A potem biedzić się przy drobnej zmianie struktury tabel w bazie...
A to bez sensu...
Wolę rozwiązanie na kształt fabryki. Potrzebuję jakichś danych, proszę o nie fabrykę. Ona się martwi skąd ma to pobrać i jak ma to przygotować. Ja oczekuję od niej gotowego i poprawnie skonfigurowanego Query.
Ja mam z kolei podobne rozwiązanie. Z tym, że fabryka zwraca mi odpowiedniego DataModule. Taka namiastka obiektu odpowiadającego danej rzeczy(np. kontrahent czy dokument). To w niej zawarta jest cała logika aplikacji. Faktem jest, że czasem tych modułów robi się dużo. Nie mniej jednak dość wygodnie się tego używa, bo taki DataModule odpowiada np. dokumentowi wraz z jego pozycjami.

Mam podobny mechanizm, ale zrealizowany zupełnie inaczej.
Idea jest taka, żeby utworzyć podstawowe zasoby (jak np. źródła danych), potem je wykorzystać w obiektach biznesowych (a więc dane okno, raport czy logika korzysta z określonych źródeł powiązanych ze sobą) a samą wizualizację tworzyć automatycznie.
Zatem mam bardzo dużo kodu ogólnego i bardzo mało specjalizowanego, ponieważ typową appkę bazo-danową robię w aplikacji bez kodowania.
W projekcie nie mam żadnych formatek, query, DataModule. Jest tego mniej.
Oczywiscie sa inne problemy - a największy to taki, że nie programuje wizualnie. W ogóle.
A tak poza konkursem - osobiście uważam, że komponenty niewizualne przy większym projekcie to zło.
Nigdy nie ma pewności, czy dany obiekt posiada ustawienia w kodzie czy w wyklikane w IDE.
Zatem wole wszystko mieć w kodzie w jednym miejscu; wtedy nie muszę się zastanawiać, dlaczego coś nie działa i czy coś nie jest ustawione inaczej na poziomie komponentu niewizualnego.

/CIACH/

0
wloochacz napisał(a):

Ponieważ IBXy nie posiadają odpowiednik Live Data Window znanego z FireDAC.
I to nie tylko z TIBTable działała "mułowato"; jak zassasz całą sporą tabelę do Qury, będzie działać tak samo mułowato...
Niestety tu jest racja. Jednak muszę dalej ciągnąć te nieszczęsne IBX'y bo za dużo kodu było by do zmiany. A to jest po prostu zaszłość z tego względu, że jak zaczynano pisać to korzystano tylko i wyłącznie z wbudowanych komponentów w C++ Buildera. Kiedyś mam nadzieję przejść na coś lepszego. Jednak to nie ode mnie zależy.

wloochacz napisał(a):

Eeehh.... o tym tez już pisałem...
To powtórzę pytanie; masz dane pochodzące z zapytania, które jest efektem długo działającej analizy danych i zwraca mało rekordów.
Niech odpalenie zapytanie trwa 3 minuty i zwraca 1K rekordów.
Ja to posortuje po stronie klienta i potrwa to 0,01 sekundy, Ty to posortujesz po stronie serwera i będzie to trwało 3 min.
Dalej uważasz, że nigdy nie zmienisz zdania?
Ok, w tym przypadku faktycznie warto odejść od mojej zasady. Na szczęście nie miałem takiej potrzeby.

wloochacz napisał(a):

Uważam, że klikanie formatek to zadanie dla małpy a nie dla programisty. Nienawidzę tego robić i dlatego tego nie robię.
Ale jest jeszcze potężna wartość dodana; specyfika mojego programu zakłada dostosowanie do warunków i wymagań konkretnego klienta.
Ja mogę zmienić układ każdego okna bez rekompilacji bezpośrednio u klienta (Panie, ja bym chciał aby tego nie było, a to było w innym miejscu a tu by przydało się widzieć to i tatmo).
Mogę też np. dodać do konkretnej formatki jakieś tam dane i wyświetlić je na danej formatce. Dane mogą pochodzić z mojego systemu lub nie. I też bez rekompilacji.
Jakbym miał to robić w sposób standardowy, to po 5 klientach umarł w butach...
Tak, samo klepanie formatek może robić i małpa. Jednak muszę się przyznać, że nie miałem styczności z systemem gdzie wszystko się konfiguruje. Ja tylko mam sparametryzowaną dużą część okien w ten sposób, że da się ustawić tak aby danych pól nie było widać, bo dany user tego nie używa. Ale o zmianie ułożenia nie ma mowy.

Mr.YaHooo napisał(a):

Mam podobny mechanizm, ale zrealizowany zupełnie inaczej.
Idea jest taka, żeby utworzyć podstawowe zasoby (jak np. źródła danych), potem je wykorzystać w obiektach biznesowych (a więc dane okno, raport czy logika korzysta z określonych źródeł powiązanych ze sobą) a samą wizualizację tworzyć automatycznie.
Zatem mam bardzo dużo kodu ogólnego i bardzo mało specjalizowanego, ponieważ typową appkę bazo-danową robię w aplikacji bez kodowania.
W projekcie nie mam żadnych formatek, query, DataModule. Jest tego mniej.
Oczywiscie sa inne problemy - a największy to taki, że nie programuje wizualnie. W ogóle.
A tak poza konkursem - osobiście uważam, że komponenty niewizualne przy większym projekcie to zło.
Nigdy nie ma pewności, czy dany obiekt posiada ustawienia w kodzie czy w wyklikane w IDE.
Zatem wole wszystko mieć w kodzie w jednym miejscu; wtedy nie muszę się zastanawiać, dlaczego coś nie działa i czy coś nie jest ustawione inaczej na poziomie komponentu niewizualnego.
Widać, że postawiłeś bardziej na napisanie narzędzia do tworzenia innych systemów niż gotowego programu który jest bardzo ściśle określony i pasuje 90% userom. Widać mamy po prostu inne targety userów :)

Trochę ten brak programowania wizualnego moim zdaniem może przeszkadzać. Mi osobiście szybciej się tworzy interfejs jak widzę jak to będzie wyglądało. Być może to jest kwestia przyzwyczajenia. Co do ustawień, to dlatego w moim zespole narzuciliśmy sobie taką zasadę, że wszystko (oprócz zapytań SQL) ma być konfigurowane podczas tworzenia danego obiektu/klasy i właściwości powinny być ustawiane z poziomu kodu. Wiadomo, że czasem się kliknie nawet przez pomyłkę w inspektorze i zmieni jakąś wartość true na false i vice versa. Takie coś co prawda zwiększa rozmiar kodu, ale eliminuje takie pomyłki w 100%.

0
Mr.YaHooo napisał(a):
wloochacz napisał(a):

Uważam, że klikanie formatek to zadanie dla małpy a nie dla programisty. Nienawidzę tego robić i dlatego tego nie robię.
Ale jest jeszcze potężna wartość dodana; specyfika mojego programu zakłada dostosowanie do warunków i wymagań konkretnego klienta.
Ja mogę zmienić układ każdego okna bez rekompilacji bezpośrednio u klienta (Panie, ja bym chciał aby tego nie było, a to było w innym miejscu a tu by przydało się widzieć to i tatmo).
Mogę też np. dodać do konkretnej formatki jakieś tam dane i wyświetlić je na danej formatce. Dane mogą pochodzić z mojego systemu lub nie. I też bez rekompilacji.
Jakbym miał to robić w sposób standardowy, to po 5 klientach umarł w butach...
Tak, samo klepanie formatek może robić i małpa. Jednak muszę się przyznać, że nie miałem styczności z systemem gdzie wszystko się konfiguruje. Ja tylko mam sparametryzowaną dużą część okien w ten sposób, że da się ustawić tak aby danych pól nie było widać, bo dany user tego nie używa. Ale o zmianie ułożenia nie ma mowy.

Każdy duży ERP (ERP, a nie coś co ERP udaje) jest zbudowany wg podobnych zasad.
Ja garściami czerpałem z rozwiązań Microsoft Business Solutions (dywizja MS odpowiedzialna za oprogramowanie dla biznesu) i jeszcze wcześniej z rozwiązań firmy Great Plains Software, które to MBS kupił (podobnie jak Axaptę i Navision).
Sam pomysł na konwencję kreowania formatek wziąłem z dokumentacji MS Dynamics AX.
Ta konwencja to był klucz do zrobienia tego czegoś - wcześniej myślałem podobnie jak Ty, że to się nie da, że lepiej to widzieć itd.
Tylko zawsze mnie to mierziło.
Po kilku latach twierdzę, że to nieprawda :)

Mr.YaHooo napisał(a):
Mr.YaHooo napisał(a):

Mam podobny mechanizm, ale zrealizowany zupełnie inaczej.
Idea jest taka, żeby utworzyć podstawowe zasoby (jak np. źródła danych), potem je wykorzystać w obiektach biznesowych (a więc dane okno, raport czy logika korzysta z określonych źródeł powiązanych ze sobą) a samą wizualizację tworzyć automatycznie.
Zatem mam bardzo dużo kodu ogólnego i bardzo mało specjalizowanego, ponieważ typową appkę bazo-danową robię w aplikacji bez kodowania.
W projekcie nie mam żadnych formatek, query, DataModule. Jest tego mniej.
Oczywiscie sa inne problemy - a największy to taki, że nie programuje wizualnie. W ogóle.
A tak poza konkursem - osobiście uważam, że komponenty niewizualne przy większym projekcie to zło.
Nigdy nie ma pewności, czy dany obiekt posiada ustawienia w kodzie czy w wyklikane w IDE.
Zatem wole wszystko mieć w kodzie w jednym miejscu; wtedy nie muszę się zastanawiać, dlaczego coś nie działa i czy coś nie jest ustawione inaczej na poziomie komponentu niewizualnego.
Widać, że postawiłeś bardziej na napisanie narzędzia do tworzenia innych systemów niż gotowego programu który jest bardzo ściśle określony i pasuje 90% userom. Widać mamy po prostu inne targety userów :)

Nie sądzę; user jak user. A aplikacja bazodanowa, to aplikacja bazodanowa.
Formularz (co prawda z kilkudziesięcioma typami kontrolek, ale to dalej tylko formularz), grid, raport i wykres.
Jedna formatka może mieć n wizualnych elementów. Każdy z nich może być osadzony na kontenerze (PageControl, GroupBox, CollapsePanel).
Co jeszcze jest potrzebne?
IMO, to wyczerpuje temat w 90% typowej aplikacji DB.
No i oczywiście do tego jest potrzebna jeszcze logika, ale to inny temat ;-)

Mr.YaHooo napisał(a):

Trochę ten brak programowania wizualnego moim zdaniem może przeszkadzać. Mi osobiście szybciej się tworzy interfejs jak widzę jak to będzie wyglądało. Być może to jest kwestia przyzwyczajenia. Co do ustawień, to dlatego w moim zespole narzuciliśmy sobie taką zasadę, że wszystko (oprócz zapytań SQL) ma być konfigurowane podczas tworzenia danego obiektu/klasy i właściwości powinny być ustawiane z poziomu kodu. Wiadomo, że czasem się kliknie nawet przez pomyłkę w inspektorze i zmieni jakąś wartość true na false i vice versa. Takie coś co prawda zwiększa rozmiar kodu, ale eliminuje takie pomyłki w 100%.

Też tak kiedyś myślałem. Ale to nie prawda, ja nie myślę jak mam tworzyć interfejs - ja ustawiam jak ma być prezentowany dane źródło danych i na jakim kontenerze ma być osadzone.
System tworzy ten formularz, a jak mi nie pasuje to ręcznie go tuninguję.

Edytor metadanych w aplikacji:
dfMetaDataEditor.jpg
Gdzie:

  1. Konfiguracja konkretnego formularza
  2. Źródła danych dla formularza
  3. Kolekcja źródeł danych z edycją ustawień w kontekście tego formularza (widać tam grupę UI, czyli jak dane mają być prezentowane)
  4. ObjectInspector do edycji obiektów metadanych.
  5. Wizualna zależność okna od innych.

Oraz wygenerowane okno (na pierwszym planie włączony edytor układu okna), które w całości działa; a więc czyta dane, zapisuje, waliduje i respektuje uprawnienia. Bez kodowania.
dfFormWithLayEditor.jpg

0
wloochacz napisał(a):

Każdy duży ERP (ERP, a nie coś co ERP udaje) jest zbudowany wg podobnych zasad.
Ja garściami czerpałem z rozwiązań Microsoft Business Solutions (dywizja MS odpowiedzialna za oprogramowanie dla biznesu) i jeszcze wcześniej z rozwiązań firmy Great Plains Software, które to MBS kupił (podobnie jak Axaptę i Navision).
Sam pomysł na konwencję kreowania formatek wziąłem z dokumentacji MS Dynamics AX.
Ta konwencja to był klucz do zrobienia tego czegoś - wcześniej myślałem podobnie jak Ty, że to się nie da, że lepiej to widzieć itd.
Tylko zawsze mnie to mierziło.
Po kilku latach twierdzę, że to nieprawda :)
Cóż, widziałem te rozwiązania o których piszesz. Jednak wydaje mi się, że aby coś takiego napisać potrzeba będzie o wiele więcej kodu niż zaklepanie zwykłej appki w standardowy nazwijmy to sposób. mam tu na myśli współczynnik w zakresie 5-10x więcej kodu. Czy tak jest trudno mi powiedzieć, bo takiego rozwiązania zwyczajnie na oczy nie widziałem od strony źródeł.

wloochacz napisał(a):

Nie sądzę; user jak user. A aplikacja bazodanowa, to aplikacja bazodanowa.
Formularz (co prawda z kilkudziesięcioma typami kontrolek, ale to dalej tylko formularz), grid, raport i wykres.
Jedna formatka może mieć n wizualnych elementów. Każdy z nich może być osadzony na kontenerze (PageControl, GroupBox, CollapsePanel).
Co jeszcze jest potrzebne?
IMO, to wyczerpuje temat w 90% typowej aplikacji DB.
No i oczywiście do tego jest potrzebna jeszcze logika, ale to inny temat ;-)
Wiadomo, że logika aplikacji to zupełnie odmienna rzecz i to raczej już się umieszcza w kodzie aplikacji. Chyba, że znowu się mylę. Co do GUI to faktycznie tych typów elementów w większości nie jest aż tyle. Raporty z kolei to trochę inna sprawa, bo przecież user/wdrożeniowiec może tworzyć zestawienia na żądanie klienta. Zatem i tak lepiej to wyciągnąć na zewnątrz. Jedynie dostarczyć jakieś standardowe zestawienia które można wczytywać z plików.

wloochacz napisał(a):

Też tak kiedyś myślałem. Ale to nie prawda, ja nie myślę jak mam tworzyć interfejs - ja ustawiam jak ma być prezentowany dane źródło danych i na jakim kontenerze ma być osadzone.
System tworzy ten formularz, a jak mi nie pasuje to ręcznie go tuninguję.
I to ładnie wychodzi? Pytam bo raz miałem styczność z takim systemem gdzie każde okno było generowane dynamicznie, jednak nie było możliwości ręcznego tuningu takiej formatki. Automat działał koślawo, a same okno nie wyglądało najładniej. Mnie to po prostu odrzuciło.

wloochacz napisał(a):

Edytor metadanych w aplikacji:
Gdzie:

  1. Konfiguracja konkretnego formularza
  2. Źródła danych dla formularza
  3. Kolekcja źródeł danych z edycją ustawień w kontekście tego formularza (widać tam grupę UI, czyli jak dane mają być prezentowane)
  4. ObjectInspector do edycji obiektów metadanych.
  5. Wizualna zależność okna od innych.
    Nie powiem. Jestem pod wrażeniem. To jest po prostu program do tworzenia systemów ;)
wloochacz napisał(a):

Oraz wygenerowane okno (na pierwszym planie włączony edytor układu okna), które w całości działa; a więc czyta dane, zapisuje, waliduje i respektuje uprawnienia. Bez kodowania.

Wygląda bardzo ładnie. W sumie nie powiedziałbym, że to zrobił automat. Co więcej, czasem moje ręcznie ustawiane kontrolki nie wychodzą tak fajnie i mam problem z umieszczeniem elementów aby to wyglądało znośnie :]

1 użytkowników online, w tym zalogowanych: 0, gości: 1