AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi Datenbankzugriff, Threads... Verständnis
Thema durchsuchen
Ansicht
Themen-Optionen

Datenbankzugriff, Threads... Verständnis

Ein Thema von haentschman · begonnen am 15. Feb 2012 · letzter Beitrag vom 17. Feb 2012
Antwort Antwort
Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#1

AW: Datenbankzugriff, Threads... Verständnis

  Alt 16. Feb 2012, 11:14
Dann gebe ich dem Thread die DB Info´s mit und er macht eine extra Connection auf... (Szenario 1).
Gestalte das ganze doch noch etwas abstrakter: Warum bittest du nicht einen "DB-Manager" um eine Query und arbeitest dann mit dieser?! Beim Start der Anwendung musst du dem DB-Manager lediglich einmal die Connection-Informationen übergeben und gut ist das. Hast du Verbindungen zu mehreren DBs, so kannst du auch sowas machen DbManager.GetQuery('oracle'); und DbManager.GetQuery('access'); .

In dieser GetQuery()-Methode wird dann automatisch geprüft, welcher Thread aufgerufen wird. Ist für den Thread noch keine Verbindung aktiv, so wird eine neue aufgebaut und die Query in diesem Kontext erzeugt.

Zudem würde ich das ganze dann auch noch mit Interfaces verknüpfen, was dazu führt, dass du dich weniger um die Speicherverwaltung kümmern musst. Ebenso abstrahierst du dann auch von der genutzten Datenbank und bietest deinem Programm eine einheitliche Schnittstelle für den DB-Zugriff an.

Leider ist das ganze bisher nur in meinem Kopf und noch nicht ganz umgesetzt Bin aber auf dem besten Weg gerade...

welche Lösung wäre akzeptabel ?
Du weißt doch von vorn herein, was genau du updaten musst, oder? Dann packe das ganze doch in einen einzigen Thread und Transaktion und gut ist. Wie lange können solche Updates denn eigentlich dauern?! oO
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)

Geändert von s.h.a.r.k (16. Feb 2012 um 11:16 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

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

AW: Datenbankzugriff, Threads... Verständnis

  Alt 16. Feb 2012, 12:04
Danke...
Zitat:
gestalte das ganze doch noch etwas abstrakter: Warum bittest du nicht einen "DB-Manager" um eine Query und arbeitest dann mit dieser?! Beim Start der Anwendung musst du dem DB-Manager lediglich einmal die Connection-Informationen übergeben und gut ist das.
Zitat:
In dieser GetQuery()-Methode wird dann automatisch geprüft, welcher Thread aufgerufen wird. Ist für den Thread noch keine Verbindung aktiv, so wird eine neue aufgebaut und die Query in diesem Kontext erzeugt.
...ich weis zwar wie du das meinst, kann das aber praktisch nicht umsetzen. Könntest du das etwas genauer erklären ? Vieleicht mit einem Schema (vereinfacht) des Quelltextes ? So nach dem Motto wer ruft von wo was auf, wer erzeugt was ?

Derzeitiger Stand:
1. DB Framework (eine Klasse, vorbereitet um mal ein Interface draus zu machen (Getter/Setter) )
1.1 von außen kann ich ggf. eine Transaktion öffnen wenn benötigt. Intern haben die zusammengehörigen SQL eine Transaktion für sich
- Save... procedure Save(aPlantScheme: TeAV_PlantScheme)
- anhand der Property PlantScheme.State wird unterschieden ob Insert/Update/Delete

in update Prozedure:
- Query1. Execute (Transaktion der Connection)
- Thread erzeugen
- im Thread Query2 und Query 3 (seperate Connection, eigene Transaktion)

wenn ich mir vom DB Framework eine Query hole (vom Thread aus ?) kann der ganze Kram trotzdem erst gemeinsam Commited werden. (evt. zu lange)

Zitat:
Dann packe das ganze doch in einen einzigen Thread und Transaktion und gut ist.
PS: ich habe die Geschwindigkeit nicht gemessen. Normalerweise geht das schnell. Über den Tellerrand blickend wäre die Konstellation, Laden erfolgt vor dem Commit, durchaus möglich.

Geändert von haentschman (16. Feb 2012 um 12:15 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#3

AW: Datenbankzugriff, Threads... Verständnis

  Alt 16. Feb 2012, 13:52
Was ich mir basteln will schaut in etwa wie folgt aus -- ich schreibe das nun rein aus dem Gedächtnis und weiß nicht, ob alles so umsetzbar ist, da ich es noch nicht zu 100% umgesetzt habe.
Delphi-Quellcode:
type
{ hier mal die Schnittstellen, wie ich sie mir grob vorstelle... }
{ keine korrekte Implementierung; in logischer Reihenfolge präsentiert }

IDbConnectionInformation = interface
  function ToString(): string;
end;

IDbConnection = interface
  procedure SetConnectionInformation(AConnectionInformation: IDbConnectionInformation);
  procedure Open();
  procedure Close();
  function GetQuery(): IDbQuery;
end;

IDbConnectionManager = interface
  procedure SetConnectionInformation(AConnectionInformation: IDbConnectionInformation; ADatabaseID: string = 'default');
  function GetConnection(ADatabaseID: string = 'default'): IDbConnection;
end;

IDbQuery = interace
  procedure SetSQL(ASQL: string);
  // procedure SetParam() -> muss ich noch schauen, wie das mache
  procedure Execute();
  function Open(): IDbDatasetEnumerator; // zum einfachen durchgehen der Datensätze
  procedure Close();
end;

IDbDataset = interface
  // für die Beschreibung eher irrelevant
end;

IDbDatasetEnumerator = interface
  // für die Beschreibung eher irrelevant
end;


// Nun eine Basisimplementierung, die die Idee von oben repräsentiert. Der Rest
// der Interfaces ist für die Idee eher uninteressant, daher überlasse ich es
// dem Leser das mal auszuprogrammieren ;)
TBaseDbManager = class(TInterfacedObject, IDbConnectionManager)
private
  FConnectionInformation : TDictionary<string, IDbConnectionInformation>;
  FConnections : TDictionary<TThreadID, IDbConnection>;
public
  function GetConnection(ADatabaseID: string = 'default'): IDbConnection;
end;

function TBaseDbManager.GetConnection(ADatabaseID: string = 'default'): IDbConnection;
begin
  FCriticalSection.Enter();
  try
    // Wenn noch keine Verbindung für den aktuellen Thread besteht, dann wird eine
    // aufgebaut
    if (not FConnections.ContainsKey(GetCurrentThreadID())) then
      FConnections.Add(GetCurrentThreadID(), DbConnectionFactory.Create(FConnectionInformation[ADatabaseID]));

    // Anschließend existiert immer eine Verbindung für den aktuellen
    // Thread, also kann eine zurückgegeben werden
    Result := FConnections[ADatabaseID];
  finally
    FCriticalSection.Leave();
  end;
end;
  


{ Nun zur Implementierung, aber nur die wichtigsten Stellen... }

// Beim Start wird der DbConnectionManager mit den nötigen Informationen gefüttert, sodass
// dieser alle Daten für den Verbindungsaufbau hat und somit automatisch Verbindungen
// zurückgeben kann.
// Ich habe einen globalen ServiceLocator, der mir auf Anfrage eine Singleton-Instanz
// eines speziellen Typs, der sich vorher registriert hat zurück gibt. Natürlich kann man
// sowas auch anders lösen.
procedure TApplication.Startup();
var
  DbConnectionInformation : TDictionary<string, IDbConnectionInformation>;
  DbConnectionManager : IDbConnectionManager;
begin
  DbConnectionInformation := LoadAndBuildDbConnectionInformation();
  // z.B.
  // DbConnectionInformation['default'] = Verbindung zu Oracle
  // DbConnectionInformation['access'] = Verbindung zu Access
  // DbConnectionInformation['access-lan'] = Verbindung zu Access-DB, die im LAN liegt

  // Fülle den DbManager mit den Verbindungsinformationen
  DbConnectionManager := ServiceLocator.GetService('database');
  for ConnectionInformation in DbConnectionInformation do
    DbConnectionManager.AddConnectionInformation(ConnectionInformation);
end;



{ und hier nun die Nutzung... für jeden Thread wird hier automatisch }
{ eine Verbindung aufgebaut und darüber gearbeitet. }

var
  DbConnectionManager : IDbConnectionManager;
  DbConnection : IDbConnection;
  Query : IDbQuery;
  Dataset : IDbDataset;
begin
  DbConnectionManager := ServiceLocator.GetService('database')
  DbConnection := DbConnectionManager.GetConnection();
  Query := DbConnection.GetQuery();

  // Natürlich geht auch
  Query := ServiceLocator.GetService('database').GetConnection().GetQuery();

  // Oder wenn man auf eine andere DB zugreifen will. Vorher muss man aber die
  // entsprechende ConnectionInfo dem DbConnectionManager zugeführt haben.
  Query := ServiceLocator.GetService('database').GetConnection('sqlite').GetQuery();

  Query.SetSQL('SELECT * FROM BlubTable');
  try
    for Dataset in Query.Open() do
    begin
      ShowMessage(Dataset.GetField('Text').ToString());
    end;
  finally
    Query.Close();
  end;
end;
Schön an der Geschichte finde ich auch, dass durch die Interface-Nutzung man sehr viel Spielraum hat. Ebenso hängt es nun nicht mehr von der darunter liegenden DB ab. Für die konkrete Instanziierung eines Objekts nutze ich Factories, die dann eine entsprechende Instanz erzeugen und passend verknüpfen.
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

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

AW: Datenbankzugriff, Threads... Verständnis

  Alt 17. Feb 2012, 08:23
Danke an alle...

Die Lösung ist viel einfacher... Ihr könnt mich prügeln. Normalerweise kommt immer als erstes das Stichwort Normalisierung. Ich habe diese alte DB Struktur "normalisiert" und diese Felder einfach übersehen. In Tabelle 2 und 3 einfach die ID aus Tabelle 1 ablegen...und gut

Sorry für die Belästigung...
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.655 Beiträge
 
Delphi 12 Athens
 
#5

AW: Datenbankzugriff, Threads... Verständnis

  Alt 17. Feb 2012, 08:24
Schön, dass wir mal drüber gesprochen haben
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von haentschman
haentschman

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

AW: Datenbankzugriff, Threads... Verständnis

  Alt 17. Feb 2012, 08:28
Ja, schon komisch das mit dem Wald und den Bäumen. Wieder mal viel zu kompliziert gedacht...
  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 02:39 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz