[0A000] ERROR: cross-database references are not implemented:

Hallo!

Wir arbeiten hier mit .Net/C# auf ODBC Connection. Mit Mysql und MsSqlServer funktioniert unser Projekt ohne Probleme aber mit PostgreSql bekomme ich obige Fehlermeldung!
Wo könnte das Problem liegen?

Obiges Problem tritt auf bei folgendem vorgehen:

  1. DataTable dataTable = myDataSet.GetDataTable(this.TableNameSQL);
  2. DataRow dataRowNew = dataTable.NewRow();
  3. set values into new datarow
  4. dataTable.Rows.Add(dataRowNew);
  5. myDataAdapter.Update(dataRowNew); <- ERROR [0A000] ERROR: cross-database references are not implemented: “MyDatabaseName.public.MyTableName”;

Das InsertCommand sieht wie folgt aus:
INSERT INTO MyDatabaseName.public.MyTableName (id, …

Randbedingungen:
myDataAdapter = new OdbcDataAdapter(“Select * From " + tableName”, connection as OdbcConnection);
DbCommandBuilder tableSpecificSqlCommandBuilder = new OdbcCommandBuilder(myDataAdapter as OdbcDataAdapter);
myDataAdapter.InsertCommand = tableSpecificSqlCommandBuilder.GetInsertCommand();
myDataAdapter.UpdateCommand = tableSpecificSqlCommandBuilder.GetUpdateCommand();
myDataAdapter.DeleteCommand = tableSpecificSqlCommandBuilder.GetDeleteCommand();
myDataAdapter.FillSchema(myDataSet, SchemaType.Mapped, tableName);
myDataAdapter.Fill(myDataSet, tableName);


Hoffe auf baldige Hilfe
Danke und Gruß
J.R.

INSERT INTO MyDatabaseName.public.MyTableName (id, ...

Du versuchst aus der aktuellen Datenbank auf Tabellen einer anderen zu verweisen. Das geht unter PostgreSQL(zumindest bis 8.3.5) nicht. Die neue 8.4 soll das aber können, AFAIR.

Gruß Uwe

Nein, 8.4 kann das auch nicht.

PostgreSQL kann schon Schemas, damit erreicht man das gleiche. Eine Datenbank ist eine logisch getrennte Einheit, da möchte man eigentlich nicht kreuz und quer drauf zugreifen können.


Btw, Advanced Server von EnterpriseDB kann das, weil Oracle das kann …

Hallo Uwe,

das Insert Statement wird automatisch vom SqlCommandBuilder aus dem Adapter und der Connection erzeugt und sollte doch auch so passen, Oder?
Wie sollte denn das “Normale” Insert Statement lauten?

Einfach :

INSERT INTO MyTableName (id, ...

???

Und wenn ja, wie erreiche ich das im DataAdapter.InsertCommand dieses dann auch steht?

Gruß
Jan

nein - ist nicht das gleiche

Hallo ads,

kannst Du das bitte mit dem Kreuz und Quer mal genauer erläutern?!
Ich beabsichtige ja nur eine neue Zeile in die Tabelle zu schreiben. Und diese Tabelle (samt Inhalt) wurde deshalb vorher in ein Dataset geschrieben, damit ich eben nicht “Kreuz und Quer” auf die DB zugreifen muß, sondern direkt auf dem Dataset auf die entsprechende Tabelle ein NewRow absetzen kann!

Gruß
Jan

Ich habe auch nicht gesagt, dass das das gleiche ist sondern dass man das gleiche erreicht. Feiner Unterschied in der Wortwahl.

Hallo,

Nun, eine Datenbank ist eine in sich geschlossene Einheit. Wer sich zu einer Datenbank verbindet oder diese wechselt, muss das gesamte Procedere der Anmeldung neu durchlaufen. Also möchte man eigentlich auch nicht, dass Anfragen über mehrere Datenbanken hinweg funktionieren.

Wenn Daten logisch zusammengehören, packt man die in eine Datenbank. Wenn Daten nicht zusammengehören, sind auch keine Anfragen über Datenbankgrenzen hinweg notwendig.



Ich beabsichtige ja nur eine neue Zeile in die Tabelle zu schreiben. Und diese Tabelle (samt Inhalt) wurde deshalb vorher in ein Dataset geschrieben, damit ich eben nicht “Kreuz und Quer” auf die DB zugreifen muß, sondern direkt auf dem Dataset auf die entsprechende Tabelle ein NewRow absetzen kann!

Tja, dein Framework macht dort irgendwo censored
Woran genau das liegt, weiß ich nicht, sorry.

Es bestätigt mich nur wieder darin, dass High-Level Frameworks grundsätzlich mehr Probleme erzeugen als sie lösen.

Du hast sowas von recht!
Warum will da nur keiner drauf hören?? Die glauben alle an diese Framework
Wunderdrogen und meinen ohne Detailwissen zur betreffenden DB würde
es schon gehen, dabei können MySQl/MSSQL/ORACLE und Postgres gar nicht
unterschiedlicher sein…

Komischerweise funktioniert unsere Framework mit MySql und MsSql und Oracle problemlos! Stichwort Factory-Pattern! :slight_smile:
“Eine” qualifizierte Antwort würde mir schon reichen! Aber man kann ja nicht alles haben! :wink:

Gruß
J.R.

Ja, jetzt.
Wart mal ab, bis die Performance kritisch wird und du dein “Ein-Pattern für alle” für verschiedene Datenbanken optimieren musst.
Du hast ja jetzt schon Probleme, weil es nicht mit allen Datenbanken funktioniert.


“Eine” qualifizierte Antwort würde mir schon reichen!

Was steht denn in den einzelnen Variablen drin, die du in deinem Programm hast?

besonders wenn sie vor lauter “auch nicht wissen” zumindest noch daran denken ueber das problem herzuziehen … das ist symptomatisch hier … und leider offenbar auch viral

Aber zurueck zum Problem …

Offensichtlich läßt Du den SqlCommandBuilder komplett automatisch das SQL-Kommando erzeugen.

Das mag zwar sehr bequem sein, aber ist hier wohl nicht zielführend. Ich kann mich erinnern, dass der SqlCommandBuilder properties bereit hält mit denen du die Erzeugung des SQL-Codes steuern kannst - an dieser Stelle solltest du dich mal schlau machen.

CatalogLocation, CatalogSeparator usw.

Evtl. hat auch der verwendete SQLDataAdapter einige Eigenschaften, die du setzen kannst um auf die Code-Generierung des SqlCommandBuilder Einfluss zu nehmen.

Bei MySQL bedient ein Prozess ja mehrere DBs … da macht es auch Sinn, die DB referenzieren zu koennen - oder der Session zu sagen welche die aktuelle DB ist auf der operiert werden soll. Bei Postgres legt man sich bei der Session auf eine DB fest - eine andere Philosophie - die auch Sinn macht.

Der SqlCommandBuilder scheint einfach vom “unguenstigen Fall” auszugehen - und grundsaetzlich den die komplette Notation für die Tabelle zu verwenden - also einen sog. full-qualified name der art database.schema.table - womit Postgres nicht umgehen kann, weils damit eigentlich auch nicht umgehen muss -> db wird durch session festgelegt. Bei Postgres kann man also nur schema.table adressieren.

Vielleicht kannst Du am SqlCommandBuilder auch einfach die Erzeugung von “fully-qualified names” abschalten … evtl. indem du CatalogLocation auf null setzt … oder den CatalogSeparator leerst … dat musst du probieren oder studieren … bin gerade nicht mehr so fit in .net

Naja ich muss fairnesshalber zugeben das ich bis Mitte der 90er auch noch den
Bullshit von der Heiligkeit der damals gängigen ORM Mappern gelaubt habe und dachte CrossDB
wäre ein must have. Die Praxis macht Dich irgendwann weise und der junge Spund da der muss
halt noche in Vollbad in der Jauche hinter sich bringen, quasi Programmierer Äquatortaufe :slight_smile:

Die bringen den Rotz auch alle Jahre wieder und immer wieder fällt die neue Generation auf den
alten Mist erneut rein.

Hier mal ein Beispiel zum selber testen:

#region connect to db and fill example table from

 DataSet dataSet = new DataSet("PG_TEST");
 DbConnection connection = new OdbcConnection(connectionString);

 DbDataAdapter dataAdapter = new OdbcDataAdapter("Select * From " + tableName, connection as OdbcConnection);
 DbCommandBuilder dbCommandBuilder = new OdbcCommandBuilder(dataAdapter as OdbcDataAdapter);
 dataAdapter.ContinueUpdateOnError = true;
 dataAdapter.InsertCommand = dbCommandBuilder.GetInsertCommand();
 dataAdapter.UpdateCommand = dbCommandBuilder.GetUpdateCommand();
 dataAdapter.DeleteCommand = dbCommandBuilder.GetDeleteCommand();
 dataAdapter.FillSchema(dataSet, SchemaType.Mapped, tableName);
 dataAdapter.Fill(dataSet, tableName);

 #endregion connect to db and fill example table from

 DataTable dataTable = dataSet.Tables[tableName];
 DataRow dataRowNew = dataTable.NewRow();
 dataRowNew["id"] = "foobar";
 dataRowNew["_inheritleafclassname"] = "foobar";
 dataRowNew["_locked"] = 0;
 dataTable.Rows.Add(dataRowNew);

 int iRecordsAffected = dataAdapter.Update(new DataRow[] { dataRowNew });
 if (dataRowNew.RowError.Trim() != String.Empty)
  {
      // Und hier ist der Fehler:
       // ERROR [0A000] ERROR: cross-database references are not implemented: "provetechr2adb.public.projects";
       // Error while executing the query
       System.Console.WriteLine(dataRowNew.RowError);
}

Würde mich interessieren wie es bei Euch damit aussieht!?

Gruß
J.R.

Ja, das werde ich mir doch mal anschauen müssen.

Ok. Das wusste ich nicht. Danke! Damit ist das Problem ja eigentlich gefunden.

Aha, werde ich gleich mal testen!

Thx,
Jan

Postgres kann (wider erwarten) mit fully-qualified names umgehen - funktioniert in 8.3 und 8.4 - ältere habe ich nicht probiert:

create table test(x int);

insert into pgtestdb.public.test(x) values (1)

Abfrage war erfolgreich durchgeführt: 1 Zeilen, 16 ms Ausführungszeit.

Kann es sein, dass die referenzierte DB nicht die aktuelle DB der Session ist? Oder anders ausgedrueckt - checke mal deine Connection - ich wette du öffnest da “die falsche DB” …

Wenn ich in der Abfrage eine andere DB referenziere kriege ich den gleichen Fehler.
Poste doch mal den connectionString :slight_smile: … auch wäre es interessant nun herauszufinden, wo du den catalog-name festlegst bzw. festlegen musst … der ja im grunde der datenbank-name ist … der sollte/muss mit der db im connection-string uebereinstimmen

string connectionString = "UID=username;PWD=pwd1234;DSN=RE_UML_POSTGRESQL";

Gehe über eine ODBC Verbindung auf die DB.

aha … und welche Postgres-Datenbank wird in dem genannten DSN verwendet?

Der Datenbank-Name den du in dem DSN findest - der muss als Catalog-Name verwendet werden.

Eventuell muß ich ja etwas im ODBC-Database-Administrator einstellen?
PostgreSQL 8.3.6 und ja der Datenbank Name stimmt.

nein …

die Sache ist folgende:

  1. in deinem ODBC DSN ist eine Datenabank eingestellt - auf welcher die ODBC connection arbeitet.

  2. du nutzt in deiner Anwendung dieses DSN - zunaechst um eine Verbindung zur DB herzustellen. Deine SQL-Statements werden mit den verwendeten .Net Komponenten erzeugt. Irgendwo in deinem Code hast du entweder eingestellt, dass deine DB angeblich MyDatabaseIrgendwie heisst - was aber nicht stimmt. Deine DB heisst auch nicht wie der DSN benannt ist, sondern so, wie du die Datenbank in Postgres erzeugt hast.

Du musst nun erreichen dass der richtige DB-name beim Erzeugen des SQL-Statements vor dem ???.schema.table erscheint. Dieser Teil wird dort als “Catalog-Name” bezeichnet - ich weiss nicht, welche Eigenschaft welcher Komponente dort verwendet wird. Irgendwas wie ein Database-Name oder DataSource-Name in der Connection-Komponente wären gute Kandidaten … wenn du ein Catalog-Name findest wäre das ein noch güterer Kandidat. … So eine Eigenschaft würde ich logischerweise dort suchen wo .Net die Code-Generierung ansiedelt - oder in Komponenten für die Datenquelle … denn der im moment falsche DB-Name wird ja auch irgendwoher genommen.