Strategiefrage: Eine DB-Verbindung für ALLE Datenbankabfragen (Zeitfaktor und wie?)
-
Hallo!
Ich greife über von CRecordset abgeleitete Klassen (alle haben eine gemeinsame selbstgeschriebene Basisklasse) per ODBC auf meine Datenbank zu.
Nun scheint das ständige Neu-Verbinden aber Zeit zu kosten (oder täuscht das?) und deswegen würde ich mich gerne einmal in InitInstance verbinden und dann nie wieder. Dann könnte ich auch besser auf eine nicht vorhandene DB reagieren.Wie realisiert man das am besten und mit dem wenigsten Aufwand?
Die Idee mit einem statischen Zeiger im BasisSet war irgendwie nicht so der Bringer.
Ist die Instanz in der App okay? Also eine Membervariable in der App-Klasse? Was hätte das für Nachteile?
-
Also ich mache die DB auch nicht jedes mal auf ich mace das mit dem von Visual vorbereiteten DB, bzw. nutze ich dieses geöffnet sein! In meiner Viewklasse habe ich dann in der Header
[cpp] class CDokumentenVerwaltungView : public CRecordView
{
protected: // create from serialization onlyDECLARE_DYNCREATE(CDokumentenVerwaltungView)
public:
//{{AFX_DATA(CDokumentenVerwaltungView)
enum { IDD = IDD_DOKUMENTENVERWALTUNG };
CDokumentenVerwaltungSet m_pSet;*
//}}AFX_DATA
[/cpp]
In der View.cpp dann nochm_pSet = &GetDocument()->m_dokumentenVerwaltungSet;
So und mit dem m_pSet kann ich doch arbeiten
m_pSet->MoveFirst();
dann brauch ich es doch nicht jedes mal zu öffnen. Beantwortet das die Frage??
-
Also ich mache die DB auch nicht jedes mal auf ich mace das mit dem von Visual vorbereiteten DB, bzw. nutze ich dieses geöffnet sein! In meiner Viewklasse habe ich dann in der Header
[cpp] class CDokumentenVerwaltungView : public CRecordView
{
protected: // create from serialization onlyDECLARE_DYNCREATE(CDokumentenVerwaltungView)
public:
//{{AFX_DATA(CDokumentenVerwaltungView)
enum { IDD = IDD_DOKUMENTENVERWALTUNG };
CDokumentenVerwaltungSet m_pSet;*
//}}AFX_DATA
[/cpp]
In der View.cpp dann nochm_pSet = &GetDocument()->m_dokumentenVerwaltungSet;
So und mit dem m_pSet kann ich doch arbeiten
m_pSet->MoveFirst();
dann brauch ich es doch nicht jedes mal zu öffnen. Beantwortet das die Frage??
-
Ich habe aber nicht ein Recordset sondern ca. 30 (Tendenz steigend).
Die von dir beschriebene Technik nutze ich auch, aber man muss ja noch sooooo viel Nebenzeugs laden:
Benutzer, Firmen, Artikel, und und und...Hier ne kleine Suche, da ne kleine Abfrage, immer schön lokal, damit der Speicher wieder frei wird - das sind viele Verbindungen.
-
Hm OK! Aber das kannst du doch auch mit alles Sets machen, oder? Also ich hab als ich mehrere Sets hatte die alle so eingebunden und das ging ganz gut. Bitte schlag mich nicht wenn es nicht ganz richtig ist.
-
Hauen werd ich dich schon nicht, dann hab ich ja keinen mehr zum Diskutieren.
Aber überleg mal: Ich habe einen Ladenbetrieb zu verwalten.
Also habe ich 3000 Kunden (ist ne halbwegs echte Zahl).
An jedem Kunden hängen tonnenweise Daten: Was er gekauft hat, Rechnungen, Meßdaten usw.
Dann gibts noch die ganzen Firmen, Krankenkassen, andere Stammdaten...Überleg mal, würdest du DAS ALLES im RAM kleben haben wollen?
-
estartu_de schrieb:
Überleg mal, würdest du DAS ALLES im RAM kleben haben wollen?
Joa die Firma soll mal schön RAM kaufen!!
Ne hase rescht
-
Ungenau deshalb verwende ich die RecordSets nicht. Man braucht für alles eine neue Klasse.
Bei jedem RDBMS dauert der Connect relativ lange. (Socket erstellen, Auth senden, Daten abfragen, Speicher aufräumen)
Deshalb ist eine Verbindung für manche auch besser. Wenn man aber viele User auf einer Datenbank hat ist der ständige Connect wiederum schlecht da es resourcen braucht. Viele RDBMS bezahlt man pro gleichzeitiger Verbindung bzw. sind auch die max. Anzahl Verbindungen eingeschränkt.
-
Sind drei Leute viele User?
Also mehr Leute sind ne echte Ausnahme und da wird dann auch ein etwas besserer eigener DB-Server stehen.WENN es denn geht - wie würdest du es machen? So wie ich die Idee hatte mit der App - oder anders?
-
Die Recordset-klasse garnicht verwenden sondern nur mit reinem SQL arbeiten.
Um die ODBC eine Wrapper schreiben so wie ich es gemacht habe.
-
Ähm, das ist glaubich eine Lösung, die ich mir für "wenn ich mal viel Zeit habe" aufhebe.
Ich werf jetzt nicht alles über den Haufen.
Ich bastel grade an meiner Idee, mal gucken obs klappt.
-
TJA, schlechtes Design wenn du die Datenbankanbindung nicht ändern kannst.
-
Ich muss "nur" die Recordsetklassen ersetzen - aber das ist genug Arbeit, oder?
33 mehr oder weniger umfangreiche Klassen ist nicht ohne.
Und bevor ich auf die Idee komme, müsstest du mir den Spaß schon schmackhaft machen. Was sind die megatollen Vorteile gegenüber der CRecordset-Methode.Ich müsste mich ja auch in die Programmierung ohne CRecordset einarbeiten. Deine Wrapperklasse ist doch "nur" für MySql, oder? Ich habe MSDE2000.
Tutorials dazu sind irgendwie auch recht rar.
-
zu den eingangsfragen:
ich frage mit einer CDatabase Instanz immer erstmal in der initinstance ab, ob ich ueberhaupt auf die DB zugreifen kann.ich kann aber nicht empfehlen, die crecordset-objekte immer offen zu halten. crecordset dabei ua das problem, dass es nicht richtig erkennt, ob die verbindung serverseitig geschlossen wird (kann ja bei einem mehrstuendigen zugriff durchaus ma der fall sein).
Esco
-
Ich wollte eigentlich nur das CDatabase-Objekt offen halten.
Das sieht gerade so aus:
CBasisSet::CBasisSet(CString f_strTabelle) : CRecordset(((CAd3App*)AfxGetApp())->GetDb())
Das gibt aber leider "Fehlermeldungen".
Kleiner Ausschnitt:[...] Optional feature not implemented State:S1C00,Native:0,Origin:[Microsoft][ODBC SQL Server Driver] Warning: Driver does not support requested concurrency. Optional feature not implemented State:S1C00,Native:0,Origin:[Microsoft][ODBC SQL Server Driver] Warning: Driver does not support requested concurrency. Warning: Setting recordset read only. [...]
Tja, und so eine "ReadOnly"-Datenbank ist irgendwie nicht so der Bringer.
-
Mein ODBC_WRAPPER ist aufgebaut wie der MySQL_Wrapper. Lediglich die CONNECT unterscheidet sich.
Schmackhaft muss ich dir auch nichts machen da ich nichts advon habe wenn du sie verwendest.Der Vorteil ist: Man muss sich nicht um das Anlegen von CDatabase-Objekten kümmern. Man legt eine Klasseninstanz an und sendet SQL-Query an die DB.
Der Connect übergibt man lediglich den DNS_Namen.
-
Wenn du das in den falschen Hals bekommen hast, dann sorry.
Du schreibst blos davon, als wäre es das Non-Plus-Ultra schlechthin - verrätst aber fast nix von Vor- oder Nachteilen.
Mal gucken, vielleicht schaue ich es mirmal im Rahmen eines kleineren (privaten) Projektes an - dann kann ich besser was dazu sagen.Zum schon vorhandenen Weg hast du aber wohl keine Ratschläge, oder?
-
Ich habe CDAtabase nie verwendet. Leider ist nicht alles in der MFC super.
Mein ODBC_Wrapper baut auf dem ODBC_API auf.
-
MSDN Lesen
CRecordset bietet explizit die Möglichkeit eine Verbindung
im Constructor zu übergeben, als CDataBase.
Damit kann man dann auf die Tabelle zugreifen.
Mit CDataBase::Open("") öffnet sich sogar der Standard ODBC Dialog.Alternativ braucht man nicht unbedingt einen eigenen ODBC Wrapper
schreiben, es gibt für ODBC die DTL, welche dies alles bereits
anbietet, und wie ich finde recht gut unterstützt. Die abfragen
können in STL Container eingelesen werden, oder über einen
eigenen DBView jeweils abgefragt werden.
Die DTL ist übrigens auch plattformunabhängig.
http://dtemplatelib.sourceforge.net/Devil
-
@Unix-Tom: Okay, danke.
Mal sehen, wann es zeitlich mal passt.@devil:
devil81 schrieb:
MSDN Lesen
CRecordset bietet explizit die Möglichkeit eine Verbindung
im Constructor zu übergeben, als CDataBase.Hab ich doch:
estartu schrieb:
Das sieht gerade so aus:
CBasisSet::CBasisSet(CString f_strTabelle) : CRecordset(((CAd3App*)AfxGetApp())->GetDb())
Hab ich versucht, geht schief, siehe oben. Das GetDb gibt einen Zeiger auf eine in der InitInstance geöffnete CDatabase zurück.
devil81 schrieb:
Mit CDataBase::Open("") öffnet sich sogar der Standard ODBC Dialog.
Und mit meinem bisher genutzten Connectstring (aus dem Recordset abgefragt) leider auch.
Das ist so nicht gewünscht...