GORM -> Mehrere Datenbanken

Das Forum ist für das Melden von Bugs gedacht. // This forum is intended to report bugs with the APF.
Gesperrt
Well
Beiträge: 263
Registriert: 25.10.2009, 11:00:19
Wohnort: Beuren
Kontaktdaten:

GORM -> Mehrere Datenbanken

Beitrag von Well » 15.03.2010, 22:37:06

Hey,

wenn ich versuche, in einer Anwendung mit verschiedenen Datenbanken / Schemas zu arbeiten, verwendet der GORM offensichtlich immer nur die Mapping-Table von der ersten Objekt-Tabelle ?!

Das sollte ja daran liegen, dass der GORM immer prüft, ob bereits eine Tabelle existiert und nur dann, wenn noch keine existiert, eine neue anlegt?! Bei __getAndInitServiceObject gibt es aber ja nur die Werte 'SINGELTON' und 'SESSIONSINGELTON' zur Verfügung, weswegen der GORM also immer als Singelton initialisiert wird?! Dadurch besteht dann ja bereits die Mapping-Table für die erste Datenbank, wenn man sich den GORM zum zweiten mal für die andere Datenbank / Schema holt?!

Ist das ein Fehler oder mache ich irgendwas falsch?

Benutzeravatar
dr.e.
Administrator
Beiträge: 4605
Registriert: 04.11.2007, 16:13:53

Re: GORM -> Mehrere Datenbanken

Beitrag von dr.e. » 15.03.2010, 23:36:42

Hallo Well,

schön dich mal wieder zu lesen. ;)
wenn ich versuche, in einer Anwendung mit verschiedenen Datenbanken / Schemas zu arbeiten, verwendet der GORM offensichtlich immer nur die Mapping-Table von der ersten Objekt-Tabelle ?!
Ich denke, das Problem ist, dass der GORM die Statements aktuell noch ohne den Namen des Schemas/Datenbank generiert. Das wollte ich in 1.12 bzwl. 1.13 anpassen. Sollte dich das aktuell aufhalten, kann ich das auch noch in dieser Woche nachholen. Oder isr das nicht das Problem?
Das sollte ja daran liegen, dass der GORM immer prüft, ob bereits eine Tabelle existiert und nur dann, wenn noch keine existiert, eine neue anlegt?! Bei __getAndInitServiceObject gibt es aber ja nur die Werte 'SINGELTON' und 'SESSIONSINGELTON' zur Verfügung, weswegen der GORM also immer als Singelton initialisiert wird?! Dadurch besteht dann ja bereits die Mapping-Table für die erste Datenbank, wenn man sich den GORM zum zweiten mal für die andere Datenbank / Schema holt?!
Der GORM unterstützt vom Design schon mehrere Datenbanken. Das wird so realisiert, dass eine GORM-Instanz immer über die Factory bezogen wird, die das Mapping an Hand des Namespaces und des aktuellen Applikations-Kenners erzeugt. Sofern du weitere Mappings in einer Instanz benötigst, können diese mit addMappingConfiguration() und addRelationConfiguration() hinzugefügt werden.
Selbstverständlich kannst du auch mehrere Instanzen mit je einem Applikations-Kenner aufsetzen und diesen für unterschiedliche Datenbanken verwenden. Hier müssen nur die Datenbank-Verbindungen auf die richtigen Ziel-Datenbanken verweisen.

Vielleicht postest du mal zwei Zeilen Quellcode für dein Vorhaben, dann können wir das einfacher diskutieren. Ich glaube nämlich noch nicht ganz verstanden zu haben, was du erreichen möchtest.
Viele Grüße,
Christian

Well
Beiträge: 263
Registriert: 25.10.2009, 11:00:19
Wohnort: Beuren
Kontaktdaten:

Re: GORM -> Mehrere Datenbanken

Beitrag von Well » 16.03.2010, 00:51:59

Moin :)

Jop, da hab ich mich wohl etwas schlecht ausgedrückt. Folgender Code:

Code: Alles auswählen

$or1 = $factory->getGenericORMapper('sites::test', 'kit_1', 'database_1');
$or2 = $factory->getGenericORMapper('sites::test', 'kit_2', 'database_2');
Das führt bei mir dazu, dass $or2 die gleiche "mappingTable" wie $or1 hat. Wenn ich nun also versuche, auf eine MySQL-Tabelle über $or2 zuzugreifen, die in der Objektdatei von "kit_2" definiert ist, kommt ein Fehler, dass diese Tabelle nicht vorhanden wäre, da die "mappingTable" von "kit_1" verwendet wird. (Ich kann nun leider nicht meinen richtigen Code posten, den hab ich nur auf dem PC, grml.)

Aber einmal angenommen, der Fehler läge nicht an mir: Die Factory des GORM's verwendet ja die Methode __getAndInitServiceObject, um den GORM schlussendlich zu bekommen. Diese Methode erwartet als letzten Parameter SESSION oder SESSIONSINGELTON, wobei ersteres der standart ist. Wenn ich daraus also schlussfolgere, wird von der Klasse insgesammt nur ein Objekt erstellt und nur die init()-Methode der Klasse erneut ausgeführt? Wenn es soweit korrekt ist, wäre es für mich auch klar wieso es nicht funktioniert: Die init()-Methode des GORMS prüft ja, ob bereits eine "mappingTable" angelegt wurde und erstellt nur dann, wenn noch keine vorhanden ist, eine neue?!

Code: Alles auswählen

if(count($this->__mappingTable) == 0) {
  $this->__createMappingTable();
}

Code: Alles auswählen

if(count($this->__relationTable) == 0) {
  $this->__createRelationTable();
}
So in etwa steht ja das im Code. Wenn ich nun den If-Block entferne, funktioniert meine obige Konstruktion auch. (Zumindest solange, bis ich wieder $or1 verwenden möchte, da davon dann ja die mappingTable von den Objekten von $or2 überschrieben wurde?!)

Nunja - Habe ich einen komplett falschen Ansatz für das Thema oder ist das ungewollt?

Benutzeravatar
Screeze
Beiträge: 1920
Registriert: 05.08.2009, 09:49:04
Kontaktdaten:

Re: GORM -> Mehrere Datenbanken

Beitrag von Screeze » 16.03.2010, 07:38:59

Hi well,
Ich bezweifle dass hier ein fehler im apf existiert, da ich ebenfalls an einer auf mehreren dbs basierenden anwendung schreibe.
Ich kann leider grad den code nicht vergleichen, da ich vom handy schreibe.
Wie benutzt du den gorm denn danach? Einzig wichtig ist, dass du objekte, die du in beiden dbs (bzw als stellvertreter in einer davon) verwendest, nicht mit den relationsfunktionen des objekts verwendest, sondern an entsprechende funktionen des jeweiligen gorm übergibst.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4605
Registriert: 04.11.2007, 16:13:53

Re: GORM -> Mehrere Datenbanken

Beitrag von dr.e. » 16.03.2010, 08:54:27

Hallo Well,

sind die beiden Konfigurations-Dateien wirklich unterschiedlich? Falls ja, poste mal einen Code mit dem sich das reproduzieren lässt, denn die Factory sollte eigentlich mit deinem obigen Code zwei unterschiedliche GORMs erzeugen. Alles andere wäre entweder ein Anwendungsfehler oder ein Bug - und ich sehe beides noch nicht ganz. :? Grund: des Cache-Key für den GORM ist eine Kombination aus allen Parametern der Factory:

Code: Alles auswählen

$cacheKey = md5($configNamespace.$configNameAffix.$connectionName.$type);
Wichtig dabei ist auch die Art der Verwendung (siehe Post von Screeze), denn wie oben gesagt, kennt der GORM (noch) kein Datenbank-Präfix.
Viele Grüße,
Christian

Well
Beiträge: 263
Registriert: 25.10.2009, 11:00:19
Wohnort: Beuren
Kontaktdaten:

Re: GORM -> Mehrere Datenbanken

Beitrag von Well » 16.03.2010, 17:35:33

Moin :)

Was ich noch vergessen habe: Ich verwende 1.12 aus dem SVN.

gorm_test_controller.php:

Code: Alles auswählen

<?php
class gorm_test_controller extends base_controller {
	public function transformContent() {
		// forum
		echo '<h1>forum</h1>';
		$GORM1 = &$this->__getORMapper1();
		$table = $GORM1->get('MappingTable');
		
		print_r($table);
		
		// user
		echo '<h1>user</h1>';
		$GORM2 = &$this->__getORMapper2();
		$table = $GORM2->get('MappingTable');
		
		print_r($table);
		
		// same objects?
		echo '<h1>Same objects?</h1>';
		echo '<p>'.(($GORM1 === $GORM2) ? 'Yes' : 'No').'</p>';
	}
	
	protected function &__getORMapper1() {
		$ormFactory = &$this->__getServiceObject('modules::genericormapper::data','GenericORMapperFactory');
		return $ormFactory->getGenericORMapper('sites::gorm_test', 'test1', 'db2');
	}
	
	protected function &__getORMapper2() {
		$ormFactory = &$this->__getServiceObject('modules::genericormapper::data','GenericORMapperFactory');
		return $ormFactory->getGenericORMapper('sites::gorm_test', 'test2', 'db1');
	}
}
?>
DEFAULT_test1_objects.ini:

Code: Alles auswählen

; Benutzer
[User]

; Kategorien
[Category]
Title = "VARCHAR(32)"

; Foren
[Forum]
Title = "VARCHAR(32)"
Description = "TEXT"
ViewAccessLevel = "INT(11)"

; Themen
[Topic]
Title = "VARCHAR(32)"
ViewAccessLevel = "INT(11)"
PostAccessLevel = "INT(11)"
Closed = "INT(11)"
Priority = "INT(11)"

; Beiträge
[Post]
Message = "TEXT"
DEFAULT_test2_objects.ini:

Code: Alles auswählen

; Benutzer
[User]
Username = "VARCHAR(16)"
Password = "VARCHAR(32)"
EMailAdress = "VARCHAR(64)"

;FirstName = "VARHCAR(32)"
;LastName = "VARCHAR(32)"

Jabber = "VARCHAR(64)"
ICQ = "VARCHAR(15)"
Skype = "VARCHAR(32)"
MSN = "VARCHAR(64)"
AvatarPath = "VARCHAR(255)"


; Gruppen
[Group]
Name = "VARCHAR(16)"
AccessLevel = "INT(2)"
Liefert bei mir folgende Ausgabe:
forum
Array ( [User] => Array ( [Table] => ent_user [ID] => UserID ) [Category] => Array ( [Title] => VARCHAR(32) [Table] => ent_category [ID] => CategoryID ) [Forum] => Array ( [Title] => VARCHAR(32) [Description] => TEXT [ViewAccessLevel] => INT(11) [Table] => ent_forum [ID] => ForumID ) [Topic] => Array ( [Title] => VARCHAR(32) [ViewAccessLevel] => INT(11) [PostAccessLevel] => INT(11) [Closed] => INT(11) [Priority] => INT(11) [Table] => ent_topic [ID] => TopicID ) [Post] => Array ( [Message] => TEXT [Table] => ent_post [ID] => PostID ) )

user
Array ( [User] => Array ( [Table] => ent_user [ID] => UserID ) [Category] => Array ( [Title] => VARCHAR(32) [Table] => ent_category [ID] => CategoryID ) [Forum] => Array ( [Title] => VARCHAR(32) [Description] => TEXT [ViewAccessLevel] => INT(11) [Table] => ent_forum [ID] => ForumID ) [Topic] => Array ( [Title] => VARCHAR(32) [ViewAccessLevel] => INT(11) [PostAccessLevel] => INT(11) [Closed] => INT(11) [Priority] => INT(11) [Table] => ent_topic [ID] => TopicID ) [Post] => Array ( [Message] => TEXT [Table] => ent_post [ID] => PostID ) )

Same objects?
Yes
Beide GORM-Objekte nutzen die gleiche Mapping-Table, obwohl bei beiden verschiedene Objektdateien angegeben wurden.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4605
Registriert: 04.11.2007, 16:13:53

Re: GORM -> Mehrere Datenbanken

Beitrag von dr.e. » 17.03.2010, 00:12:46

Hallo Well,

danke für den ausführlichen Code zum nachvollziehen. Das ist in der Tat ein Bug in der Factory. Es darf unter keinen Umständen ein GenericORRelationMapper als Typ SINGLETON oder SESSIONSINGLETON innerhalb der Factory erzeugt werden, weil sonst die identischen Objekte aus dem Aufruf hervorgehen. Das hattest du weiter oben schon richtig gesehen!

Ich habe daher der Methode die neue Signatur

Code: Alles auswählen

public function &getGenericORMapper($configNamespace,$configNameAffix,$connectionName,$debugMode = false)
;
gegeben, denn der Typ muss mit dem Erzeugen der Factory bestimmt werden. Möchtest du also den GORM als SESSIONSINGLETON erzeugen, muss der Mapper mit

Code: Alles auswählen

$gormFact = &$this->__getServiceObject('modules::genericormapper::data','GenericORMapperFactory','SESSIONSINGLETON');
$orm = &$gormFact->getGenericORMapper('my::namespace','config_sub_key','db_connection'[,true|false]);
erzeugt werden, im SINGLETON-Fall lediglich mit

Code: Alles auswählen

$gormFact = &$this->__getServiceObject('modules::genericormapper::data','GenericORMapperFactory');
$orm = &$gormFact->getGenericORMapper('my::namespace','config_sub_key','db_connection'[,true|false]);
da SINGLETON in __getServiceObject() der default Wert ist.

Da dieser Bug einige Änderungen in bestehenden Modulen mit sich bringt, habe ich nur den Fix an sich, nicht aber das Refactoring der bisherigen Komponenten mit ins SVN eingecheckt. Ziehe dir bitte die aktuelle Version von 1.12 aus dem SVN und schau mal ob es nun funktioniert. Bei mir lokal konnte ich das mit

Code: Alles auswählen

echo '<h1>Same objects?</h1>';
echo '<p>$GORM1 === $GORM2: '.(($GORM1 === $GORM2) ? 'Yes' : 'No').'</p>';
echo '<p>$GORM1 === $GORM1: '.(($GORM1 === $GORM1) ? 'Yes' : 'No').'</p>';
echo '<p>$GORM2 === $GORM2: '.(($GORM2 === $GORM2) ? 'Yes' : 'No').'</p>';
erfolgreich testen.
Viele Grüße,
Christian

Benutzeravatar
dr.e.
Administrator
Beiträge: 4605
Registriert: 04.11.2007, 16:13:53

Re: GORM -> Mehrere Datenbanken

Beitrag von dr.e. » 17.03.2010, 00:21:19

Hallo Well,

ich habe in weiteren Tests gerade gemerkt, dass sich mit der Änderung Probleme bei der Initialisierung der DB-Connections ergeben. Diese müssen natürlich lazy wieder nach dem De-Serialisieren erzeugt werden. Bitte nutze den Mapper zunächst nur im SINGLETON-Modus, das funktioniert aktuell.

Sorry nochmal für die Verwirrung, ich melde mich sobar auch das behoben ist! :roll:

@Ralf: genau das war unser Fehler beim letzten Mal. Es wurde die DB-Connection nicht wieder initialisiert. Das kann ich aber mit einem __wakeup() lösen, in dem die DB-Connection wieder initialisiert wird.
Viele Grüße,
Christian

Benutzeravatar
dr.e.
Administrator
Beiträge: 4605
Registriert: 04.11.2007, 16:13:53

Re: GORM -> Mehrere Datenbanken

Beitrag von dr.e. » 17.03.2010, 00:36:57

Hallo zusammen,

nun ist auch das SESSIONSINGLETON-Problem gelöst und der Mapper funktioniert nach einem unserialize mit neuer DB-Connection.

@Ralf: damit sollte auch dein Problem gelöst sein! ;)
Viele Grüße,
Christian

Benutzeravatar
Screeze
Beiträge: 1920
Registriert: 05.08.2009, 09:49:04
Kontaktdaten:

Re: GORM -> Mehrere Datenbanken

Beitrag von Screeze » 17.03.2010, 14:20:14

Hi,
@Ralf: genau das war unser Fehler beim letzten Mal. Es wurde die DB-Connection nicht wieder initialisiert. Das kann ich aber mit einem __wakeup() lösen, in dem die DB-Connection wieder initialisiert wird.
korrekt, hab mich auch wieder erinnert. Ich glaub ich hatte dich da sogar gefragt warum das nicht bei einem wakeup wieder geladen wird, aber irgendwie haben wir das richtige problem da nicht erkannt, da wir den workaround schon hatten...
@Ralf: damit sollte auch dein Problem gelöst sein! ;)
Naja ich benutz meine zwischenfactory ja sowieso, weil ich meine mapping tables aus mehreren dateien zusammenstelle (je 2 für MEMORY bzw. MyISAM),
aber ich schau mal ob ich das jetzt noch vereinfachen kann dadurch.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4605
Registriert: 04.11.2007, 16:13:53

Re: GORM -> Mehrere Datenbanken

Beitrag von dr.e. » 17.03.2010, 15:31:35

Hallo Ralf,

ok. Die Doku habe ich auch schon angepasst und das Thema in das Migrations-HOWTO von 1.12 aufgenommen.

@Well: konntest du die Änderung schon testen?
Viele Grüße,
Christian

Benutzeravatar
Screeze
Beiträge: 1920
Registriert: 05.08.2009, 09:49:04
Kontaktdaten:

Re: GORM -> Mehrere Datenbanken

Beitrag von Screeze » 17.03.2010, 16:03:04

Ich hab die änderung mal in meine komponente übertragen - gibt bisher keine Probleme.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4605
Registriert: 04.11.2007, 16:13:53

Re: GORM -> Mehrere Datenbanken

Beitrag von dr.e. » 18.03.2010, 00:26:30

Hallo Ralf,

das klingt sehr gut. :)

@Well: any experience yet?
Viele Grüße,
Christian

Well
Beiträge: 263
Registriert: 25.10.2009, 11:00:19
Wohnort: Beuren
Kontaktdaten:

Re: GORM -> Mehrere Datenbanken

Beitrag von Well » 23.03.2010, 22:07:36

Ua, ganz vergessen zu antworten. :)

Jop, funktioniert nun ohne probleme - Dankeschön. :)

@edit: Wops, mein fehler

Gesperrt

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast