Przechwytywanie alertów bazy danych FDEventAlerter.

0

Witam serdecznie.
Zwracam się do Was o poradę jak poprawnie skonfigurować i uruchomić mechanizm alertów dla bazy MS SQL Server 2008 przy użyciu FireDac-a (pracuję na Delphi XE7).
Jest tam stosowna klasa/komponent TFDEventAlerter.
Do tej pory udało mi się uruchomić alerty ale dostaję tylko powiadomienie podczas „insertów” do tabeli. Polecenie sql-owe update wykonuje się poprawie ale alert się nie generuje :/
Posiłkując się kodem że strony http://codeverge.com/embarcadero.delphi.firedac/working-with-fdeventalerter-and-sq/1090353
Tak w zasadzie to nie rozumiem składni do definiowania tego alertu, chodzi o kod:

 
FDEventAlerter1.Names.Add('QUEUE=?');
FDEventAlerter1.Names.Add('SERVICE=?');
FDEventAlerter1.Names.Add('CHANGE1=ev1;select id, name from dbo.Test');

Z tych szczątkowych informacji jakie są podane na: http://docwiki.embarcadero.com/RADStudio/XE7/en/Database_Alerts_(FireDAC)

składnia jest taka: CHANGE<index>=<message>;<SELECT query>
do czego służy <SELECT query> ?
Czy tym poleceniem <SELECT query> można pobrać np. identyfikator „zainsertowanego” rekordu ?
Czy dla MS SQL-a jest to w ogóle możliwe aby w alercie zwrócić taką informację?

Tak samo nie mam pojęcia do czego służą definicje: 'QUEUE=?' (kolejka) oraz 'SERVICE=?' (no niby serwis ale jaki ?)

Mam takie rozwiązanie na bazie oracle tam mam DBMS_ALERT.SIGNAL do którego przekazuje parametry w „trigerach” i działa to super z FireDac.

Znalazłem też informację: MS SQL Server Query Update Notification (automatic notification)
na samym dole strony: http://docwiki.embarcadero.com/RADStudio/Seattle/en/Data_Change_Notifications_(FireDAC)

Czyli MS SQL Server generuje taki alert automatycznie ??? dla oracle jawnie wołam DBMS_ALERT.SIGNAL.

1

Jak rozumiem chciałbyś aby MSSQL informował sam o jakiejś operacji. Ja niedawno miałem podobną potrzebę i temat właśnie rozwiązałem przy użyciu notyfikacji, a nie alertów.
W praktyce wygląda to tak. Tworzysz swój typ np.:
tworzysz assemblies:

CREATE ASSEMBLY kbudpNotification
  AUTHORIZATION [dbo]
FROM 
  ...
WITH PERMISSION_SET = UNSAFE
GO

tu oczywiście przy tworzeniu z jakiegoś fajnego edytora baz danych (np EMS SQL Manager) wybierz DLL napisaną w C#
następnie typ:

CREATE TYPE dbo.kbudpNotification
EXTERNAL NAME kbudpNotification.kbudpNotification
GO

i tylko w procedurze/triggerze wywołujesz:

@ubr BIT = kbudpNotification::taskStatus();   

jak sama nazwa wskazuje moja kbudpNotification.dll wysyła informacje na konkretny port udp natomiast taskStatus() to oczywiście nazwa funkcji w DLL. Trochę roboty ale działa ;)

0

Dzięki woolfik za sugestię, jednak kompletnie nie wiem o co Ci chodzi z tym:

woolfik napisał(a):

...wybierz DLL napisaną w C#

Czyli co mam w c# napisać procedurę/metodę „zamknąć” ją w dll. która wysyła coś po udp a trigger woła jakąś wyeksportowaną metodę z tej dll ? I dalej w moim programie nasłuchiwać na gniazdku co dostaję na udp ?

Szczerze wolał bym rozwinąć temat który przedstawiłem w pierwszym poście, bo tak jak napisałem
w przypadku inserta dostaję alert/notyfikację.
Chciał bym tym sposobem dostać alert o „update” i identyfikator rekortdu na jakim odbyło się uaktualnienie, bądź identyfikator nowo wstawionego rekordu.
Już sporo czasu poświęciłem na szukanie informacji na stronach M$ ale tam jest to bardzo fragmentarycznie opisane. O przykładach no docwiki.embarcadero pod FireDac-a to nie wspomnę ...

0

@PrzemysławWiśniewski dokładnie tak problem właśnie będzie z tym "identyfikatorem nowego rekordu" wyobraź sobie, że masz 100 userów pracujących w jednym momencie na danej tabeli. Gdy pojawi się nowy wpis lub zmiana rekordu to ma iść notyfikacja do userów w stylu: "Odśwież listę" i grid ma sam się odświeżyć. Wszystko super ale jeśli np tabela jest "spora" i select z niej trwa chwilę a userzy klikają jak szaleni to efekt będzie taki, że nim Ci się pierwsza notyfikacja odświeży to już 100 innych jest w kolejce ... Druga sprawa, że jeśli widok masz zawężony do usera (czyli np zadanie jest per user i ktoś wystawia zadanie dla tego usera) to notyfikacje lecą dla wszystkich a wykorzystując moją metodę możesz sobie również zwrócić IDUsera dzięki czemu odświeżasz listę tylko gdy notyfikacja dotyczy jego listy, a nie listy innych userów. Ponadto możesz przekazać całą listę (np w postaci XML, JSON) parametrów dzięki czemu po notyfikacji nie musisz robić select aby pobrać dane bo dostaniesz je w XML. Jeżeli jest to system produkcyjny i planujesz dalej go rozwijać to zalecam tą metodę więcej pracy ale mniej problemów później ;)

0
woolfik napisał(a):

@PrzemysławWiśniewski dokładnie tak problem właśnie będzie z tym "identyfikatorem nowego rekordu" wyobraź sobie, że masz 100 userów pracujących w jednym momencie na danej tabeli. Gdy pojawi się nowy wpis lub zmiana rekordu to ma iść notyfikacja do userów w stylu: "Odśwież listę" i grid ma sam się odświeżyć.

Nie grid, a zmienione rekordy.
Akurat w FireDAC jest to do zrobienia i to inteligentnie.
A więc, można odświeżyć pojedyncze rekordy - dodane, zmienione i usunięte.
Można odświeżyć tylko to co ma sens, a sens na liście ma odświeżanie tylko tych rekordów, które zostały pobrane na klienta. Resztę po co, skoro i tak zostaną dociągnięte na żądanie. Przynajmniej ja tak działam, bardzo uważnie podchodzę do tego co pobieram z serwera, jak często i ile danych ma to zwrócić.
I to wszystko jest do zrobienia, trzeba się tylko zapoznać z manualem FireDACa i poczytać o:
LocateEx (tam jest taka fajna opcja lxoNoFetchAll, do której, nie chwaląc się, sam przyczyniłem i zaproponowałem jej dodanie. No i jest ;-))
SourceEof
FetchMode
RefreshUnknownRecord
RefreshRecord

Wszystko super ale jeśli np tabela jest "spora" i select z niej trwa chwilę a userzy klikają jak szaleni to efekt będzie taki, że nim Ci się pierwsza notyfikacja odświeży to już 100 innych jest w kolejce ...

Patrz wyżej...

</quote> Druga sprawa, że jeśli widok masz zawężony do usera (czyli np zadanie jest per user i ktoś wystawia zadanie dla tego usera) to notyfikacje lecą dla wszystkich a wykorzystując moją metodę możesz sobie również zwrócić IDUsera dzięki czemu odświeżasz listę tylko gdy notyfikacja dotyczy jego listy, a nie listy innych userów. </quote> OKiej, a co za problem wysłać ten ID Usera?

Ponadto możesz przekazać całą listę (np w postaci XML, JSON) parametrów dzięki czemu po notyfikacji nie musisz robić select aby pobrać dane bo dostaniesz je w XML. Jeżeli jest to system produkcyjny i planujesz dalej go rozwijać to zalecam tą metodę więcej pracy ale mniej problemów później ;)

Tu już ciut pojechałeś za daleko...
Jak bym się miał tak bawić, to olałbym bazę danych i przeszedł całkowicie na serwer aplikacyjny.

0

@wloochacz tak jak rozmawialiśmy, jakbyś znalazł chwilę to wrzuć tu konkretne rozwiązanie jak ustawić firedac i jak skonfigurować serwer aby notyfikacje np na update rekordu były przekazywane z serwera do klienta.

0

@wloochacz dołączam się do prośby kolegi woolfik, jak możesz zamieś przykład jak zmusić FireDac-a do opisywanego wyżej działania z FDEventAlerter.

@woolfik dzięki za twoją propozycję rozwiązania mojego problemu, jeśli masz to przetestowane to
jak nie uda mi się tego ogarnąć w FD wezmę pod uwagę. Jednak na razie mam nadzieję że uda mi się to osiągnąć w FireDac-u. W oracle działa mi to rewelacyjnie przez FDEventAlerter tak więc myślę że w MSSQL jest to zrobienia.

Pozdrawiam.

0

Panowie, to potrwa... Problem polega na tym, że nie mam na to w ogóle czasu. Ten tydzień całkowicie odpada.

1

Dla potomnych,

Sorry Panowie i Panie że odgrzebuję tak stary temat ale może się to komuś przydać.

Od dawna w kilku aplikacjach stosuję powiadamianie oparte na FDEventAlerter z bazą MS SQL. Zazwyczaj działa to idealnie ale ostatnio trafiłem na zagwozdkę. Dorabiałem powiadamianie do bardzo starej aplikacji klienta która korzystała jeszcze z bazy MS SQL 2005 (migrowanej z MSDE), nie działało to więc zrobiłem update silnika bazodanowego do wersji MS SQL 2008 R2 ze wszystkimi service packami. Jest to ostatnia wersja bazy z którą działa aplikacja.

Jednak okazało się że problem nadal występuje, po próbie aktywacji komponentu FDEventAlerter (oczywiście prawidłowo zainicjowanego i ustawionego) dostaje komunikat:
screenshot-20200129092503.png

Nasiedziałem się nad tym zakładając że popełniłem jakiś błąd (niestety w Internecie wiedza na ten temat jest szczątkowa). Wczoraj w końcu odkryłem źródło problemu. Okazało się że baza po takich migracjach nadal ma ustawiony poziom kompatybilności na SQL Server 2000 (80)
screenshot-20200129093025.png

należy to zmienić na coś nowszego ale kompatybilnego z oprogramowaniem (u mnie SQL Server 2008 (100) i powiadomienia zaczną działać.

Pozdrawiam.

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