AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi TFDEventAlerter HowTo
Thema durchsuchen
Ansicht
Themen-Optionen

TFDEventAlerter HowTo

Ein Thema von haentschman · begonnen am 28. Mai 2021 · letzter Beitrag vom 3. Jun 2021
Antwort Antwort
Benutzerbild von haentschman
haentschman

Registriert seit: 24. Okt 2006
Ort: Seifhennersdorf / Sachsen
5.388 Beiträge
 
Delphi 12 Athens
 
#1

TFDEventAlerter HowTo

  Alt 28. Mai 2021, 08:14
Datenbank: MSSQL • Version: 2017 • Zugriff über: FireDAC
Hallo...

Mein letzter Strohhalm...euch zu fragen.

SOLL:
Die Datenbank "soll" ein Event (pro Tabelle) auslösen. Der Client soll dann seine Datenmenge aktualisieren können.

IST:
Ich habe alles ausprobiert...es wird kein Event ausgelöst.

Infos:

http://docwiki.embarcadero.com/RADSt...ngen_(FireDAC)
http://docwiki.embarcadero.com/RADSt...ngen_(FireDAC)

Beispiel ausprobiert:
https://stackoverflow.com/questions/...ql-server-2012

Ich habe mich für die Variante "_FD_EVENTS UPDATE notification" entschieden.

1. Broker ist on
2. _FD_EVENTS Tablelle wurde erstellt
3. 'evtUsers' Event wurde als Datensatz in der Tabelle angelegt (über Register der Komponente)
(Die Komponente versucht jedesmal den Datensatz anzulegen -> stille Exception bei Vorhandensein...macht Spaß im Debug. )
Zitat:
---------------------------
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt Project1.exe ist eine Exception der Klasse EMSSQLNativeException mit der Meldung '[FireDAC][Phys][ODBC][Microsoft][SQL Server Native Client 11.0][SQL Server]Verletzung der PRIMARY KEY-Einschränkung "PK___FD_EVEN__737584F7CB96DC61". Ein doppelter Schlüssel kann in das dbo._FD_EVENTS-Objekt nicht eingefügt werden. Der doppelte Schlüsselwert ist (evtUsers).' aufgetreten.
---------------------------
Anhalten Fortsetzen Hilfe
---------------------------

---------------------------
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt Project1.exe ist eine Exception der Klasse EMSSQLNativeException mit der Meldung '[FireDAC][Phys][ODBC][Microsoft][SQL Server Native Client 11.0]OZum Festlegen dieses Attributs müssen bestimmte andere Attribute festgelegt werden. Einstellung des Attributs wird ignoriert.' aufgetreten.
---------------------------
Anhalten Fortsetzen Hilfe
---------------------------
4. Signal function der Komponente erhöht den Wert des Values
5. TFDPhysMSSQLDriverLink wird der gebraucht?
6. Beim Beenden oder Close kommt eine stille Exception bei der Freigabe des Threads der Komponente.
Zitat:
---------------------------
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt Project1.exe ist eine Exception der Klasse $C0000005 mit der Meldung 'access violation at 0x004c893c: read of address 0x0000003c' aufgetreten.
---------------------------
Anhalten Fortsetzen Hilfe
---------------------------
Delphi-Quellcode:
procedure TFDPhysMSSQLEventAlerter.InternalAbortJob;
begin
  FWaitThread.Terminate; // <- hier
  FWaitCommand.AbortJob(True);
end;

Ergebnis:

kein Event wird ausgelöst.

Was habe ich vergessen? Was ist falsch?

Wie kommt denn der Broker von MSSQL ins Spiel? Der Alerter braucht doch nur im Task den Wert des Values vergleichen und das Event auslösen..oder?


Testcode:
Delphi-Quellcode:
procedure TForm1.ale1Alert(ASender: TFDCustomEventAlerter; const AEventName: string; const AArgument: Variant);
begin
  qry1.Refresh;
end;

procedure TForm1.btn1Click(Sender: TObject);
begin
  con1.Connected := True;

  qry1.SQL.Text := 'select * from Users';
  qry1.Open;
end;

procedure TForm1.btn2Click(Sender: TObject);
begin
  con1.Close;
end;

procedure TForm1.btn3Click(Sender: TObject);
begin
  ale1.Signal('evtUsers', 1);
end;
Delphi-Quellcode:
object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 511
  ClientWidth = 933
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  DesignSize = (
    933
    511)
  PixelsPerInch = 96
  TextHeight = 13
  object grd1: TDBGrid
    Left = 32
    Top = 88
    Width = 889
    Height = 401
    Anchors = [akLeft, akTop, akRight, akBottom]
    DataSource = ds1
    TabOrder = 0
    TitleFont.Charset = DEFAULT_CHARSET
    TitleFont.Color = clWindowText
    TitleFont.Height = -11
    TitleFont.Name = 'Tahoma'
    TitleFont.Style = []
  end
  object btn1: TButton
    Left = 32
    Top = 40
    Width = 75
    Height = 25
    Caption = 'Open'
    TabOrder = 1
    OnClick = btn1Click
  end
  object btn2: TButton
    Left = 113
    Top = 40
    Width = 75
    Height = 25
    Caption = 'Close'
    TabOrder = 2
    OnClick = btn2Click
  end
  object btn3: TButton
    Left = 264
    Top = 40
    Width = 75
    Height = 25
    Caption = 'btn3'
    TabOrder = 3
    OnClick = btn3Click
  end
  object con1: TFDConnection
    Params.Strings = (
      'DriverID=MSSQL'
      'MARS=No'
      'Server=XXX'
      'User_Name=Blubb'
      'Password=Test'
      'Database=Bla')
    Connected = True
    LoginPrompt = False
    Left = 824
    Top = 24
  end
  object qry1: TFDQuery
    Connection = con1
    Left = 32
    Top = 200
  end
  object ds1: TDataSource
    DataSet = qry1
    Left = 80
    Top = 200
  end
  object ale1: TFDEventAlerter
    Connection = con1
    Names.Strings = (
      'evtUsers')
    SubscriptionName = 'Events'
    Options.AutoRegister = True
    Options.MergeData = dmNone
    Options.AutoRefresh = afNone
    OnAlert = ale1Alert
    Left = 824
    Top = 80
  end
  object lnk1: TFDPhysMSSQLDriverLink
    Left = 760
    Top = 24
  end
end

Geändert von haentschman (28. Mai 2021 um 08:33 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#2

AW: TFDEventAlerter HowTo

  Alt 28. Mai 2021, 10:28
Funktioniert denn das FireDAC.TFDEventAlerter Beispiel?

Falls du die Samples nicht installiert hast: https://github.com/Embarcadero/RADStudio10.3.3Demos
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
lowmax_5

Registriert seit: 9. Mai 2003
Ort: Münster, NRW
258 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: TFDEventAlerter HowTo

  Alt 28. Mai 2021, 10:45
Hi,
ich hatte es vor ein paar Wochen ebenfalls versucht unter MSSQL (2008) den TFDEventAlerter mit den Demos zum laufen zu bekommen und habe alle angegebenen Verfahren getestet. Leider vergebens- das Thema wurde daher erst einmal zurück gestellt. Es wurde nun mit Poll-Verfahren umgesetzt...

Unter Firebird hat es nach 5 Min. funktioniert . Nur die Portfreigabe/Firewall dabei beachten, da auf einem anderen Port <> 3050 kommuniziert wird.

Geändert von lowmax_5 (28. Mai 2021 um 11:06 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.475 Beiträge
 
Delphi 12 Athens
 
#4

AW: TFDEventAlerter HowTo

  Alt 28. Mai 2021, 11:41
Könnte auch mit der verwendeten Delphi-Version zusammenhängen. Bei Sydney gab es da wohl ein paar Verbesserungen. Wenn ich Zeit finde, kann ich das Beispiel ja mal mit 10.4.2 und MSSQL ausprobieren.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

Registriert seit: 24. Okt 2006
Ort: Seifhennersdorf / Sachsen
5.388 Beiträge
 
Delphi 12 Athens
 
#5

AW: TFDEventAlerter HowTo

  Alt 29. Mai 2021, 09:11
Moin...
Zitat:
Wenn ich Zeit finde, kann ich das Beispiel ja mal mit 10.4.2 und MSSQL ausprobieren.
Durch das Rumprobieren habe ich folgendes festgestellt:

Der Alerter legt mit jedem Register den Service und einen Queue (wahrscheinlich wegen der Einstellungen) mit jeweils einer GUID im Namen an. Diese werden beim Beenden wieder entfernt. Soweit so gut. Wenn das Programm aber "abgeschossen" oder über die IDE beendet wird, bleiben die Einträge in den Systemtabellen vorhanden.

Ist wahrscheinlich technisch nicht anders machbar...

PS: Ich hatte auch einmal nur den Namen ohne GUID gesehen...aber nur einmal.

Danke

PS:
Zitat:
Es wurde nun mit Poll-Verfahren umgesetzt..
...da werde ich mir auch einen Thread basteln der das erledigt. Ich würde das über eine Tabelle mit GUID, statt BigInt (da ist irgendwann Schluß), lösen. Die Datenmengen sind sogar hardgecodet in der Tabelle registriert. Der Thread schaut...Änderung GUID -> Event.
evt. Vorteil: kein Broker benötigt.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#6

AW: TFDEventAlerter HowTo

  Alt 29. Mai 2021, 13:06
Hast du es mal "manuell" versucht?
(CREATE EVENT NOTIFICATION)

Im Postgres hatten wir auch immer wieder mit dem TPgAlerter Problemchen,
also dass der oftmals einfach garnicht empfing, oder nach einem Reconnect die Arbeit ebenfalls einstellte (obwohl er darauf eigentlich reagieren sollte, so weit ich es im Code sah).

Am Ende hab ich nun im AfterConnect der Connection die Registrierung selbst gemacht (EXECUTE mit einem Registrieungs-Statement)
und dann es kommt nun im OnNotify der TPgConnecton an ... und das nun auch sehr zuverlässig. (bisher keine Probleme mehr bemerkt)
$2B or not $2B

Geändert von himitsu (29. Mai 2021 um 13:09 Uhr)
  Mit Zitat antworten Zitat
braunbaer

Registriert seit: 15. Okt 2008
Ort: Vorarlberg
118 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: TFDEventAlerter HowTo

  Alt 30. Mai 2021, 15:43
Könnte auch mit der verwendeten Delphi-Version zusammenhängen. Bei Sydney gab es da wohl ein paar Verbesserungen. Wenn ich Zeit finde, kann ich das Beispiel ja mal mit 10.4.2 und MSSQL ausprobieren.
Das wäre super.
Ich sollte dies ebenfalls haben, bringe es aber einfach nicht zum laufen.
Das FDEventAlerter1Alert wird nicht getriggert.

Hoffe, du findest die Ursache...
Gebhard Blank
  Mit Zitat antworten Zitat
braunbaer

Registriert seit: 15. Okt 2008
Ort: Vorarlberg
118 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: TFDEventAlerter HowTo

  Alt 3. Jun 2021, 08:18
Hat zu diesem Thema jemand eine Lösung?

Mir wäre das viel lieber, als alle paar Sekunden auf neue oder geänderte Daten zu prüfen.

Bin für jeden Tipp oder kleines Beispiel dankbar...
Gebhard Blank
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

Registriert seit: 24. Okt 2006
Ort: Seifhennersdorf / Sachsen
5.388 Beiträge
 
Delphi 12 Athens
 
#9

AW: TFDEventAlerter HowTo

  Alt 3. Jun 2021, 08:27
Hallöle...
Zitat:
Mir wäre das viel lieber, als alle paar Sekunden auf neue oder geänderte Daten zu prüfen.
Das ganze war mir zu unsicher. Ich habe mich fürs "Polling" entschieden...

1. EventTypes
Delphi-Quellcode:
TRefreshDataType = (rdtComplete)
...
2. In der Datenbank eine Tabelle:
Code:
create table _Events
(
  ID int IDENTITY(1,1) NOT NULL,
  EventType int NOT NULL,
  EventName nvarchar(30) NOT NULL,
  EventCurrentGUID uniqueidentifier NOT NULL,
  CONSTRAINT Events_pk PRIMARY KEY CLUSTERED (ID ASC)
)
create index ixEventType on _Events (EventType)
GO

/* Events */
insert into _Events (EventType, EventName, EventCurrentGUID) values (0, 'Complete', NEWID())
GO

/* Trigger*/
create trigger TR_Complete on Complete for insert, update, delete as
begin
  update _Events set EventCurrentGUID = NEWID() where EventType = 0
end
GO
3. Ein Thread der das ganze überwacht (Auszug)
Delphi-Quellcode:
procedure TDatabaseEventThread.Execute;
var
  Qry: TFDQuery;

  procedure LoadEvents;
  begin
    Qry.Open;

    while not Qry.Eof do
    begin
      FGUIDDict.Add(Qry.FieldByName('EventType').AsInteger, TGuidField(Qry.FieldByName('EventCurrentGUID')).AsGUID);
      Qry.Next;
    end;
  end;

  procedure CheckEvents;
  var
    PairCurrent: TPair<Integer, TGUID>;
  begin
    FGUIDDictCurrent.Clear;
    Qry.Close;
    Qry.Open;

    while not Qry.Eof do
    begin
      FGUIDDictCurrent.Add(Qry.FieldByName('EventType').AsInteger, TGuidField(Qry.FieldByName('EventCurrentGUID')).AsGUID);
      Qry.Next;
    end;

    for PairCurrent in FGUIDDictCurrent do
    begin
      if FGUIDDict.ContainsKey(PairCurrent.Key) then // sicher ist sicher
      begin
        if not (FGUIDDict.Items[PairCurrent.Key] = PairCurrent.Value) then
        begin
          FGUIDDict.Items[PairCurrent.Key] := PairCurrent.Value; // zurückschreiben
          FLastEvent := TRefreshDataType(PairCurrent.Key); // DataType für Synchronisierung
          SyncOnDataChange;
        end;
      end;
    end;
  end;

begin
  inherited;
  Qry := FDatabase.CreateQuery;
  try
    Qry.SQL.Text := FDatabase.GetSQLByName('DB_EVENTS');

    LoadEvents;

    while not Self.Terminated do
    begin
      if FDatabase.IsEventDataChangeActive then
      begin
        CheckEvents;
      end;
      Sleep(1000);
    end;
  finally
    Qry.Free;
  end;
end;
Wenn ein Event eintritt, verteile ich das über eine Message an die Forms und die gibt das an die entsprechende Formlogik weiter. Die Formlogik kennt die Events auf die sie reagieren soll und aktualisiert ggf. die Datenmenge der Form.

...fertsch.

Geändert von haentschman ( 3. Jun 2021 um 08:46 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:48 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz