Autor Beitrag
lapadula
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 180
Erhaltene Danke: 10



BeitragVerfasst: Do 11.05.17 20:40 
Hallo,

ich möchte etwas in die Datenbankprogrammierung einsteigen und will einen Datenbankkonverter schreiben.
Sollte ungefähr so aussehen, das man eine bestehende Datenbank, ohne Inhalt hat und eine die ähnlich strukturiert und mit Daten gefüllt ist.
Nun sollen die Inhalte aus der befüllten DB, in die leere Datenbank geschrieben werden und zwar über ein GUI.

Konkretes Beispiel:

Kunde A möchte von Anbieter X zu Anbieter Y wechseln. Die Datenbank möchte er mitnehmen und der Firma Y zur verfügung stellen. Die Firma Y muss die Inhalte nun in die eigene Datenbank einpflegen und da mehrere Kunden zu Firma Y wechseln, will man nicht für jede Datenbank extra einen Konverter schreiben. Diese Aufgabe der Konvertierung sollen nicht die Programmierer erledigen, sondern jeder Mitarbeiter soll das können, daher das GUI.

Das heisst das Programm sollte so abstrakt wie möglich sein. Die Mitarbeiter sollten einfach die Tabellen auswählen können, die übernommen werden und in die eigene Datenbank geschrieben werden.

Ich habe mich ein wenig bei Google umgesehen und finde einfach nichts zu diesem Thema, außer Anbieter die ein fertiges Programm anbieten.

Hat das schon jemand umgesetzt und kann berichten auf was man achten sollte, welche schwierigkeiten auf einen zukommen und ob es da bestimmte Pattern gibt.

Danke im vorraus
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Do 11.05.17 21:48 
Sowas nennt man meist eine DataPump (damit hättest du zumindest einen weiteren Suchbegriff).

Sowas in der Art habe ich schon mehrmals gemacht aber noch nie mit dem Hintergrund beliebiger Datenbank Typen. Habe da auch Vorstellungsprobleme mit der Beliebigkeit ;)
Das primäre Problem werden die Metadaten/Schemadaten werden. Simples Select/Insert zum Transport wird fast überall identisch funktionieren. Das erzeugen von Tabellen wird zumindest ähnlich sein. Funktionales eher gar nicht (Zum Beispiel Trigger zumindest nicht wenn du zwischen unterschiedlichen Modellen verschieben will. Aka aus T.SQL wird nicht plötzlich PL-SQL oder umgekehrt).
Da Tabellen in Relation stehen musst du die Abhängigkeiten berücksichtigen da kommen dann halt Metadaten/Schemadaten ins Spiel und da wird der SQL Standard dünn bzw. nicht eindeutig genug um davon auszugehen das sich die meisten Datenbanken ähnlich/identisch verhalten. Insofern solltest du im Auge behalten das du dich da auf eine testbare Menge von Datenbankmodellen (und deren Versionen) beschränken musst.

Zu berücksichtigen

A.) Du musst die Beziehungen der Tabellen ermitteln. Denn wenn du z.B eine Tabelle A woanders hinschieben willst geht das nur wenn du auch alle Tabellen von denen A abhängt mitverschiebst. Es gibt zwar einen Standard für Schemainformationen der ist aber nicht immer umgesetzt bzw. richtig umgesetzt. Wenn du das nicht auf SQL Ebene ermitteln willst sondern gegenüber einem generischen Treibermodell wie ODBC oder OLEDB ermitteln willst dann kannst du leider auch nicht davon ausgehen das jeder Treiber dieses Models diese Daten veröffentlicht. Schemadaten über so eine einheitliches Treibermodell zu veröffentlichen ist ein kann und leider kein muss.

B.) Du musst beim verschieben vorher alle Integritätsregeln/Trigger etc. ausschalten und nachher natürlich wieder einschalten. Trigger könnten dir Daten erzeugen die du eigentlich auch kopieren wolltest. Und zu versuchen Daten einfach in der richtigen Reihenfolge zu kopieren so das Integritätsregeln erfüllt bleiben ist extrem schwer. Denke zum Beispiel an selbst referenzieren Tabellen. Da musst du nicht nur die richtige Tabellenreihenfolge berücksichtigen sondern dann auch die Reihenfolge der einzelne Datensätze in der Tabelle. Wen du dann darin auch noch Datensätze hast die sich gegenseitig referenzieren (jaja extreme cornercase und schlechtes Design ich weiß) dann wird richtig spaßig. Dann müsstest du erst ein Insert des einen Datensatz machen ohne die Referenz dann den anderen Datensatz inserten und dann ein update auf den ersten Datensatz um die Referenz nachzuziehen. Diese Komplexität kann man immer weiterspinnen. Ist also eher eine Sackgasse. Das was funktioniert ist abschalten und wieder einschalten der Integritätsregeln.

C.) Du mußt dir Gedanken machen um die Transaktionsgrenzen beim moven. Zu klein (z.B. je Datensatz) könnte zu langsam sein zu groß (je Tabelle) könnte problematisch werden weil dem System die Resourcen ausgehen und die Datenbank fliegt dir um die Ohren. Die zu wählenden Transaktionsgrenzen (und eigentlich auch das zu wählende Locking Model der Transaktionen) ist eigentlich Abhängig vom MOdel der Zieldatenbank. Es gibt da kein "one size fits all".
lapadula Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 180
Erhaltene Danke: 10



BeitragVerfasst: Do 11.05.17 22:31 
Super danke!

Allein der Suchbegriff hilft mir weiter.


Das ganze beschränke ich auf Microsoft SQL, sollte das ganze ein wenig vereinfachen.

Die Tabellen sind schon alle da, das Model ist gegeben, es sollen dann nur die gewünschten Daten aus der der einen in die andere insertet werden (natürlich mit allem drum und dran wie die Abhängigkeiten usw. )
doublecross
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 149
Erhaltene Danke: 27

Windows 7
C#; Visual Studio 2015
BeitragVerfasst: Fr 12.05.17 16:01 
Hallo,

der Wusch ein solches Tool zu schaffen, ist sicher schon bei vielen aufgekommen, ich habe aber noch keine wirklich individuelle Lösung gesehen, welche auch vom Endbenutzer zu bedienen wäre.
Das Problem dabei ist, das die "ähnlichen" Datenbankmodelle meist gar nicht so ähnlich sind.

Angenommen du willst von Buchaltungssoftware A zu Buchaltungssoftware B wechseln, dann sieht die "Kndenverwaltung" von BHS-A in der Datenbnak vielleicht so aus:

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
+---------------
| Customer
+---------------
| custID 
| custName
| deliveryStreet
| deliveryZIP
| deliveryCity
| billingStreet
| billingZIP
| billingCity
| deliveryisbillingadress
+---------------


während BHS-B das ganze so abbildet:

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
+---------------
| Customer
+---------------
| custID 
| custName
+---------------

+---------------
| Adresses
+---------------
| adressId
| Street
| ZIP
| City
+---------------

+---------------
| CustomerAdressLink
+---------------
| ID
| custID 
| adressId
| adressType
+---------------


Mal ganz abgesehen davon, dass BHS-B es potentiell ermöglicht auch mehrere Liefer- und Rechnungsadressen zu hinterlegen, wird es auch tricky die eine Struktur auf die andere abzubilden. Ein einfaches Mapping, welches man technisch weniger versierten Nutzern vielleicht gerade noch zumuten kann reicht dann schon nicht mehr aus.
Der Nutzer muss eine Möglichkeit bekommen einen Teil seiner Daten der Customer-Tabelle von BHS-A in die Tabelle Customer aus BHS-B zu schreiben zwei andere Teile in je einen neuen Datensatz von Tabelle Adresses und die Relation muss er dann auch noch in CustomerAdressLink hinterlegen.
Nicht viel schöner wäre es, denn du anders herum Migrieren willst, also von Software B in Software A, da musst du dann mindestens einer Möglichkeit bieten, dass der Nutzer sich eine View erstellt, in welcher die Daten der drei Tabellen aus BHS-B zusammengeführt werden. Auch das wird kaum in einer für Normalsterbliche verständlichen Form möglich sein.

Wenn du solche Fälle hingegen weg definierst, dürfte es nicht besonders schwer ein Tool zum übertragen der Daten zu erstellen, seine Nützlichkeit wird sich nur in grenzen halten.
lapadula Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 180
Erhaltene Danke: 10



BeitragVerfasst: Sa 13.05.17 19:35 
So ungefähr hab ich mir das auch vorgestellt.

Zu BHS A:

Wenn ich in BHS B eine Beziehung zwischen dem Kunden und einer Adresse habe und bei BHS A nicht, dann kann ich doch einfach als Endnutzer später angeben, welche Tabelle, welche Spalte verknüpft werden soll.

Anders herum, also wenn es eine Beziehung gibt, ich aber in meiner DB keine habe, dann schaue ich was hinter der ID steckt und schreibe den Zelleninhalt als Text in meinen Datensatz.

Oder stelle ich mir das zu leicht vor?
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: So 14.05.17 13:09 
Im speziellen kann es leicht sein im allgemeinen sicher nicht.

Wenn es systemabhängige unterschiedliche Datenstrukturen sind (ich dachte zuerst du wolltest auch die Tabellenstrukturen übernehmen, für dein Problem ist der Begriff DataPump daher eher ungeeignet) die du aufeinander abbilden willst dann steckst du tief auch in der Logik des jeweiligen Systems und implizit vorhandene Informationen müssen möglicherweise explizit angegeben werden. Neben Mapping von Feldern musst da also Wissen über die Logik der beiden beteiligten Anwendungen (Ziel,Quelle) haben (in der Anwendung oder beim User davor) um Logik anzupassen.

Wenn du wie im Beispiel von [url]DoubleCross[/url] die Adressen mappst dann musst du den passenden adressType in der Zieltabelle ermitteln. Also Strukturinformationen (ich weiß es ist eine Lieferadresse weil es in den deliveryXXX Feldern steht) in eine expliziten Wert für das adressType Feld ändern. In dem Beispiel brauchst du nachher zwei Datensätze in CustomerAdressLink und Adresses. Du musst also nicht nur die Felder mappen sondern auch sagen welche Felder zusammen einen neuen Datensatz in der Zieltabelle ergeben und wie das mit den Mapping Tabellen bei n-n Beziehungen funktionieren soll. Wenn du das Zielsystem entsprechend dem Beispiel auch richtig verwenden willst müsstest du eigentlich sogar prüfen ob es die Adresse nicht bereits gibt und die wiederverwenden und nur einen Datensatz in CustomerAdressLink erzeugen.

Welches Feld wohin gehört ist nur ein kleineres Problem da können sich viel weitere ergeben.
- zu übernehmende PrimaryKeys sind eher nicht wiederverwendbar da entweder bereits vergeben oder es liegt ein ganz anderes PrimaryKey System vor (AutoIncrement, GUIDs, gar keine PKs, zusammengesetzte aus Daten)
- logisch gleiches dargestellt als anderer Typ und das nicht zwingen in der gleichen Anzahl Felder (Datum mal als Datumstyp, Integer, String, aufteilt in einzelne Felder für Tag/Monat/Jahr etc.)
- unterschiedliches Encodings
- Constraints in der Datenbank. Also Dinge die in der Quelle erlaubt sind sind es im Ziel plötzlich nicht mehr. (Kunden mit gleichen Namen oder E-Mail Adressen)
Es gibt sicher dutzende problematischer Strukturen die wenn man sie ineinander umformen muss/will zu Problemen führen
- Ziel erlaubt strukturell weniger als die Quelle (Kunden hatten mehrere Adressen in der Quelle im Ziel darf es aber nur noch eine geben)
- implizite Daten die nicht in der Datenbank enthalten sind (z.b. adressType muss nirgendwo in der Datenbank stecken. Die gültigen Werte und deren Bedeutung kann auch ausschließlich in der Anwendung bekannt sein)

Die Liste ist beliebig erweiterbar. Darum glaube ich ist ein generischer Ansatz für beliebige Anwendungs-datenbanken erstmal außer Reichweite. Du solltest vielleicht erstmal ermitteln über welche Probleme du fällst bei 2 konkreten Produkten ohne auszuwählenden User dazwischen (falls du das noch nicht getan hast). Dann überlegen wie du einen auswählenden User dazwischen bekommst. Dann bekommst du auch ein Gefühl wie viel Freiheit man dem unbedarften User dazwischen geben kann so das da auch was sinnvolles raus kommen kann. Und dann kann man überlegen ob es eine Chance gibt das für weitere Produkte zu erweitern. Für beliebige Produkte halte ich für eher unwahrscheinlich zumindest mit der Vorbedingung unbedarfter User soll konvertieren. Ich halte es für möglich ein Tool zu schreiben bei dem man nachher keinen echten Programmieraufwand hat. Aber es sollte ein technisch bewanderter User sein. Der Grundverständnis für relationale Datenbanken hat, Wissen über die Funktionsweise von Quell und Zielanwendung und am besten vor Scripting nicht zurückschreckt um Probleme mit nicht in der DB vorhandenen Daten zu lösen und Informationen hinzuerfindenden bzw. aus anderen Quellen zu ziehen.

Für diesen Beitrag haben gedankt: doublecross
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 14.05.17 17:13 
- Nachträglich durch die Entwickler-Ecke gelöscht -
lapadula Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 180
Erhaltene Danke: 10



BeitragVerfasst: So 14.05.17 21:31 
Dickes Danke für die Infos, das ganze wird wohl nicht so dynamisch wie erhofft aber nicht schlimm..

@Frühlingsrolle

Konvertieren war vllt wirklich das falsche Wort. Der Inhalt soll soweit wie möglich von A nach B übernommen werden. Die Tabellen oder Datensätze die es in B nicht gibt oder nicht gebraucht werden, sollen auch nicht übernommen werden. Das Datenbankmodell soll von A nach B "konvertiert" werden.
Frühlingsrolle
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: So 14.05.17 21:55 
- Nachträglich durch die Entwickler-Ecke gelöscht -
doublecross
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 149
Erhaltene Danke: 27

Windows 7
C#; Visual Studio 2015
BeitragVerfasst: Mo 15.05.17 11:14 
Hi,
user profile iconlapadula hat folgendes geschrieben Zum zitierten Posting springen:
Dickes Danke für die Infos, das ganze wird wohl nicht so dynamisch wie erhofft aber nicht schlimm.


das ist leider das Problem dabei, Universell und einfach geht meiner Einschätzung nach in dem Fall nicht zusammen.
Wie kompliziert es in einem Konkreten Fall wird hängt von den Beteiligten Programmen ab. Daher musst du jetzt erst einmal die Arbeitsweisen beider Programme verstehen (bzw. deren Datenbankstruktuen) und dann überlegen wie du es übertragen bekommst. Bei einem Großteil der Daten wird es sicher recht einfach, da du sie nur Kopieren und Mappen musst, bei den Schwierigen Fällen musst du das dann sehr speziell und Händisch nacharbeiten. Das Stichwort für das was du vorhast wäre übrigens Migration keine Ahnung ob es da gute fertige Tools gibt, die du nutzen kannst.

Viel Erfolg auf jeden Fall.