Laden...

Datenbank Versions Check und Updates

Erstellt von baer999 vor 13 Jahren Letzter Beitrag vor 13 Jahren 2.157 Views
B
baer999 Themenstarter:in
375 Beiträge seit 2007
vor 13 Jahren
Datenbank Versions Check und Updates

Wie kann ich es sicherstellen, dass Datenbankänderungen in meiner Entwicklung bei Testern und Kunden auch automatisch geupdatet werden?

Also bspw. Erstelle ich eine neue Tabelle, füge einer Tabelle ein Feld hinzu etc.
Wenn der Kunde eine neue Version des Programms mit der alten Datenbankversion ausführen will, wird schnell auf Fehler laufen ("Feld x ist nicht bekannt" o.ä.).
thx

H
208 Beiträge seit 2008
vor 13 Jahren

Naja, das sind eigentlich 2 getrennte Probleme:

  1. Dein Programm muß erkennen daß die Datenbank auf die es zugreift alt ist und aktualisiert werden muß

  2. wenn die DB aktualisiert werden muß, dann muß es die Aktualisierung durchführen

Nummer 1 ist ziemlich simpel - füge eine neue Tabelle mit einer einzigen Spalte und einem einzigen Datensatz in die Datenbank ein. In dieser Tabelle speicherst Du eine Versionsnummer (am einfachsten die des Programmes).

Dein Programm liest dann bei jedem Start den Wert aus der Datenbank und vergleicht ihn z.B. mit seiner eigenen Versionsnummer.
Und wenn Du z.B. von Programmversion 2.3 zu Version 2.4 ein Feld in einer Tabelle hinzugefügt hast, und das Programm beim Start merkt daß es selbst Version 2.4 ist und auf einer DB mit Version 2.3 läuft, dann muß es dieses Feld automatisch in der Datenbank anlegen.
Das Programm muß also eine Art eingebaute Datenbankhistorie haben.

Nummer 2 wird u.U. komplizierter, je nachdem wie Deine Datenbankänderungen so aussehen.
Solange einfach nur neue leere Felder hinzugefügt werden (und die erstmal leer bleiben) ist das alles kein Problem.
Komplizierter könnte es nur werden, wenn z.B. ein neues Feld bei allen bestehenden Datensätzen auch gleich mit Daten gefüllt werden muß, die sich wiederum ergeben aus den Inhalten von mehreren anderen Feldern usw.
Oder wenn eine Tabelle gelöscht wird und deren Inhalte vorher teilweise in andere Tabellen verschoben werden müssen...

Das muß Dein Programm dann auch alles können, und das für alle möglichen Kombinationen von Programmversion und Datenbankversion.

DAS wird die meiste Arbeit verursachen.

F
10.010 Beiträge seit 2004
vor 13 Jahren

Migrator.NET oder FluentMigrator machen Punkt 2 recht einfach.

B
baer999 Themenstarter:in
375 Beiträge seit 2007
vor 13 Jahren

Ich will ausschließlich leere Felder anfügen oder ganze neue Tabellen mit leeren Feldern anlegen.
Wie kann ich das bewerkstelligen? Kann ich dafür einfach SQLs auf die DB loslassen?

F
10.010 Beiträge seit 2004
vor 13 Jahren

Ist jetzt keine ernst gemeinte Frage, oder?

  1. Die Beiden von mir geposteten FW können sowas.

  2. Natürlich generieren die auch nur SQL, denn eine andere Möglichkeit gibt es nicht.

B
baer999 Themenstarter:in
375 Beiträge seit 2007
vor 13 Jahren

Also ich speichere die entsprechenden SQL Statements in einer Datenbanktabelle, jeweils einer Versionsnumemr zugeordnet.

Gibt es in Visual Studio die Möglichkeit sich bspw. das SQL Statement von einer Erstellung einer Tabelle generieren zu lassen oder ähnliches? Denn sonst müsste ich jede DB Änderung selbst als SQL Statement definieren.

U
1.688 Beiträge seit 2007
vor 13 Jahren

Hallo,

welche Probleme hast Du mit den von FZelle genannten Frameworks?

1.552 Beiträge seit 2010
vor 13 Jahren

Hallo baer999,

Gibt es in Visual Studio die Möglichkeit sich bspw. das SQL Statement von einer Erstellung einer Tabelle generieren zu lassen oder ähnliches? Denn sonst müsste ich jede DB Änderung selbst als SQL Statement definieren.

Ja gibt es
Hab z.Z. nur keinen SQL-Server installiert, aber:
Rechtsklick auf tablelle->scripts, und da sollte es drinnen sein.

Gruß
Michael

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

3.825 Beiträge seit 2006
vor 13 Jahren

Hallo,

ich mache das so :

  • Die Datenbankstruktur schreibe ich in den Sourcecode

  • Beim Start des Programms prüfe ich ob sich die Versionsnummer geändert hat.

  • Wenn ja dann gehe ich alle Felder durch und lege die an die fehlen und verlängere die die zu kurz sind (per SQL-Skript das dynamisch erzeugt wird).

Ich habe keine Versionshistorie, das wäre mir zu kompliziert, muss ja auch alles getestet werden.

"Keep it simple"

Versionshisorie mit Diff-Skript ist bei mir bei Dotnetnuke schon oft genug schief gelaufen. Das heisst dann : Datenbank-Backup zurückspielen und Skripts erneut laufen lassen. Bei meiner Applikation brauchte ich das noch nie.

Da ich das für mehrere verschiedene Datenbanken mache kann ich kein fertiges Framework nehmen. Es gibt da nämlich so einige Eigenheiten. Beispiel :

  • Sql Compact : Index löschen bevor Feld verlängert werden kann
  • MySQL : Alle Felder einer Tabelle in einem Befehl anlegen / verlängern, sonst dauert der Programmstart einige Stunden bei gefüllen Tabellen.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

B
baer999 Themenstarter:in
375 Beiträge seit 2007
vor 13 Jahren

OK, das hört sich sehr gut an und spart erheblich Arbeit,
wie meinst du das "die Datenbankstruktur liegt im Quellcode"?

3.825 Beiträge seit 2006
vor 13 Jahren

Ungefähr so :


//	Tabelle	Spaltenname	Feldtyp (Länge)
string dbstru = @"
	ad	ad_nr           float
	ad	ad_match        nvarchar (20)
	ad	ad_anrede       nvarchar (4)
	ad	ad_name1        nvarchar (40)
	ad	ad_name2        nvarchar (40)
	ad	ad_strasse      nvarchar (40)
	ad	ad_hausnr       nvarchar (10)
	ad	ad_lkz          nvarchar (3)
	ad	ad_ort          nvarchar (40)
";

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

B
baer999 Themenstarter:in
375 Beiträge seit 2007
vor 13 Jahren

Ok, das würde ich dann einfach in eine Tabelle packen und diese DataRow für DataRow durchgehen.

Wie prüft man komfortabel, ob eine Spalte in einer Datenbank existiert? Muss ich per Adapter eine DataTable füllen die ein Select mit * auf die DB ausführt und diese DataTable dann prüfen oder geht es einfacher? thx

3.825 Beiträge seit 2006
vor 13 Jahren

Array oder Collection geht auch.

Ich mach das ungefähr so :

public bool FieldExists(string dat, string fld)
{
	bool feldvorhanden = true;
	string sqlstr = "";
	DbConnection conn = CreateConnection();
	DbCommand cmd;
	try
	{
		conn.Open();
		sqlstr = "select " + fld + " from " + dat + " where 0=1";
		cmd = CreateCommand(sqlstr, conn);
		int anz = cmd.ExecuteNonQuery();
	}
	catch (Exception ex)
	{
		if (ex is SqlException) if (((SqlException)ex).Number == 207) feldvorhanden = false;
	}
	conn.Close();
	return feldvorhanden;
}

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

1.552 Beiträge seit 2010
vor 13 Jahren

sqlstr = "select " + fld + " from " + dat + " where 0=1";

Ich hoffe dass du in deinem Programm mit SQL-Parametern arbeitest und dies nur ein Beispiel ist.

Gruß
Michael

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

3.825 Beiträge seit 2006
vor 13 Jahren

Hallo Michael,

danke für den Hinweis. Ich stelle erst nach und nach auf Parameter um. Da es sich hier nicht um Benutzereingaben handelt, die bearbeitet werden kann zwar nichts passieren, aber besser wäre es schon.

Baer999 : Mein Code war nur ein Beispiel, wenn Du den verwendest bitte so ändern dass er mit Parametern arbeitet.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

B
baer999 Themenstarter:in
375 Beiträge seit 2007
vor 13 Jahren

"A parameter is not allowed in this location. Ensure that the '@' sign is in a valid location or that parameters are valid at all in this SQL statement."

        public bool DBFieldExist()
        {
            bool FieldExist = true;
            DBVersionAdapter.Connection.Open();
            System.Data.SqlServerCe.SqlCeCommand Cmd = new System.Data.SqlServerCe.SqlCeCommand("", DBVersionAdapter.Connection);
            Cmd.CommandText = "SELECT @fld FROM DBVersion WHERE 1=0";
            Cmd.Parameters.Add("@fld", "Version");
            MessageBox.Show(Cmd.ExecuteScalar().ToString());
            DBVersionAdapter.Connection.Close();
            return true;
        }

Wie kann ich das mit Parametern lösen?

1.552 Beiträge seit 2010
vor 13 Jahren

Parameter kommen in die WHERE Klausel rein.

SqlCommand comm =new SqlCommand(SELECT * FROM table WHERE spalte=@value.........);
comm.Parameters.AddWithValue("@value","wert Einzufügen");

Mein Blog
Meine WPF-Druckbibliothek: auf Wordpress, myCSharp

3.825 Beiträge seit 2006
vor 13 Jahren

Hallo Baer,

dann kann man das nicht mit Parametern lösen. Lass sie weg.

Wenn Du Benutzereingaben verarbeitest dann pass auf dass nur Zeichen enthalten sind die erlaubt sind, das sind Zahlen, Buchstaben und Unterstrich.

Nicht erlaubt u.a. : , . ' ´ ` "

In meiner Applikation kann das vorkommen beim Report-Generator, bei dem der Anwender angeben kann welche Felder abgefragt werden.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

B
baer999 Themenstarter:in
375 Beiträge seit 2007
vor 13 Jahren

Ja aber wie kann ich dann die obige Abfrage machen, ob eine Spalte in einer Tabelle überhaupt existiert?

2.082 Beiträge seit 2005
vor 13 Jahren

Es ist toll jemand zu sein, der nichts von der persönlichen Meinung Anderer hält. - frisch-live.de

V
162 Beiträge seit 2010
vor 13 Jahren

Hi,

bei großen Datenbanken kann man aus Systemtabellen die Informationen auslesen.

MSSQL Server , Oracle und Firebird hab ich es selber schon gemacht. (MYSQL geht das denk ich auch)
Bei SQLite wird das wohl eher nicht funktionieren.

"frisch" hat da schon Beispiele für den MSSQL Server gepostet.
Es ist auf jeden fall der richtige Weg.
TIP: Probleme kannst du vielleicht mit den Berechtigungen in der DB bekommen. Bei "BerndFfm" und seiner Methode trift dies nicht zu.

Du wirst dich immer individuell einlesen müssen.

Das Leben ist schön!

3.825 Beiträge seit 2006
vor 13 Jahren

Ja aber wie kann ich dann die obige Abfrage machen, ob eine Spalte in einer Tabelle überhaupt existiert?

Mein Programmschnipsel oben gibt einen boolschen Wert zurück :

True : Spalte existiert

False : Spalte existiert nicht

Viper : Ja, genau. Ausserdem lässt sich meine Methode einfach so erweitern, dass sie auch mit anderen Datenbanken funktioniert, z.B. MySQL, Sql Compact, PostgreSQL, Oracle ...

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3