AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi Datenbank per Code umbenennen

Datenbank per Code umbenennen

Ein Thema von OG Karotte · begonnen am 11. Mai 2008 · letzter Beitrag vom 12. Mai 2008
Antwort Antwort
OG Karotte
(Gast)

n/a Beiträge
 
#1

Datenbank per Code umbenennen

  Alt 11. Mai 2008, 23:25
Datenbank: SQLite • Version: 3.5.8 • Zugriff über: ZEOS
Hallo zusammen,

ich versuche eine Datenbank per Code umzubenennen. Hierzu schließe ich die Datenbank perDb.Disconnect um sie anschließend per RenameFile(OldName, NewName) umzubenennen. Dummerweise meldet Windows, das die Datei nicht umbenannt werden kann, da sie noch in Benutzung sei.

Ich vermute, das das Disconnect nicht ganz ausreicht, ich möchte aber auch das Datenbankobjekt nicht freigeben / zerstören, um anschließend die Datei umzubenennen und unter dem neuen Namen wieder zu erstellen.
Gibt es noch andere Möglichkeiten???
  Mit Zitat antworten Zitat
Nuclear-Ping
(Gast)

n/a Beiträge
 
#2

Re: Datenbank per Code umbenennen

  Alt 11. Mai 2008, 23:35
Versuch mal folgendes:

1.) RENAME DATABASE[list=1] TO <newname>; 2.)
SQL-Code:
CREATE DATABASE <newname> FROM TEMPLATE[list=1];
DROP DATABASE oldname;
Sonst verhindert wahrscheinlich der ganze Prozess deiner Anwendung das Umbenennen der Datenbank. In dem Falle wird dir nichts anderes übrig bleiben, als die Datenbank irgendwie vor dem Start deiner eigentlichen Anwendung umzubenennen, zB per Batch-Script.
  Mit Zitat antworten Zitat
OG Karotte
(Gast)

n/a Beiträge
 
#3

Re: Datenbank per Code umbenennen

  Alt 11. Mai 2008, 23:57
Funktioniert leider nicht, da SQLite diese Befehle leider nicht kennt
  Mit Zitat antworten Zitat
omata

Registriert seit: 26. Aug 2004
Ort: Nebel auf Amrum
3.154 Beiträge
 
Delphi 7 Enterprise
 
#4

Re: Datenbank per Code umbenennen

  Alt 12. Mai 2008, 00:10
Ich machte so etwas ähnliches mit ZEOS + Embedded Firebird.

Da mache ich auch nur ein Disconnect dann allerdings ein CopyFile, das geht aber problemlos.

Eventuell liegt es ja auch an SQLite.

Das ist auf jeden Fall sehr mysteriös.

Gruss
Thorsten
  Mit Zitat antworten Zitat
OG Karotte
(Gast)

n/a Beiträge
 
#5

Re: Datenbank per Code umbenennen

  Alt 12. Mai 2008, 00:23
Nun, an ein Kopieren der Datei habe ich auch schon gedacht, empfinde dies aber als etwas umständlicher als ein einfaches umbenennen...

... ich werde es aber trotzdem mal probieren (und wenn es nur als Zwischenlösung ist).

... funktioniert auch nicht (gleiches Ergebnis wie bei Rename)
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#6

Re: Datenbank per Code umbenennen

  Alt 12. Mai 2008, 03:34
Zitat von OG Karotte:
Dummerweise meldet Windows, das die Datei nicht umbenannt werden kann, da sie noch in Benutzung sei.
Ein beliebter Fehler ist, dass die Datenbank noch von der Delphi IDE offengehalten wird,
da man ja zur Entwicklungszeit Tabellen oder Queries (manchmal auch unbewusst) aktiv schalten kann.
  Mit Zitat antworten Zitat
OG Karotte
(Gast)

n/a Beiträge
 
#7

Re: Datenbank per Code umbenennen

  Alt 12. Mai 2008, 10:07
Zitat von sx2008:
Ein beliebter Fehler ist, dass die Datenbank noch von der Delphi IDE offengehalten wird,
da man ja zur Entwicklungszeit Tabellen oder Queries (manchmal auch unbewusst) aktiv schalten kann.
Leider ist auch dies nicht der Fall, da ich keine Datensensitiven Elemente und daher auch keine Designtime-Connection verwende. Der Fehler tritt ebenfalls bei geschlossener IDE auf.

Im Prinzip mache ich nichts weiter als:
  • Datenbank anlegen (geschieht unter ZEOS automatisch bei setzen des Datenbank Namens und dem ersten Zugriff auf selbige)
  • Tabellen und ein paar Grunddaten per SQL-Script anlege (ExecSQL)
und dann ein Datenbank.Disconnect ausführe um die DB umbenennen zu können. => Error 32
  Mit Zitat antworten Zitat
Nuclear-Ping
(Gast)

n/a Beiträge
 
#8

Re: Datenbank per Code umbenennen

  Alt 12. Mai 2008, 10:17
Wie schon gesagt wird deine ganze Anwendung der Prozess sein, der den Zugriff verhindert. Vielleicht ist ZEOS oder dein SQlite Server auch nur so eingerichtet, dass sie die Datei so öffnen, dass kein geteilter Zugriff ermöglicht wird?

Daher der Vorschlag:
- Anwendung erzeugt Batch, startet Batch und beendet sich selber
- Batch:
--- Warten, bis Anwendung wirklich zu ist
--- REN[list=1] <newdb>
--- Anwendung.exe
- Anwendung löscht Batch
  Mit Zitat antworten Zitat
OG Karotte
(Gast)

n/a Beiträge
 
#9

Re: Datenbank per Code umbenennen

  Alt 12. Mai 2008, 11:20
Zitat von Nuclear-Ping:
Wie schon gesagt wird deine ganze Anwendung der Prozess sein, der den Zugriff verhindert. Vielleicht ist ZEOS oder dein SQlite Server auch nur so eingerichtet, dass sie die Datei so öffnen, dass kein geteilter Zugriff ermöglicht wird?

Daher der Vorschlag:
- Anwendung erzeugt Batch, startet Batch und beendet sich selber
- Batch:
--- Warten, bis Anwendung wirklich zu ist
--- REN[list=1] <newdb>
--- Anwendung.exe
- Anwendung löscht Batch
Danke für den Vorschlag, aber das ist mir zu umständlich für diese "einfache" Funktionalität. Dann laß ich lieber kein Umbenennen zu

Was ZEOS oder SQLite angeht: Mir ist dort keine Einstellung bekannt, die dieses Verhalten ändert.

...

Ich hab' jetzt mal ein Testprojekt aufgesetzt und siehe da es funktioniert (Ich war mir auch sicher das es vorher schonmal funktioniert hat). Stellt sich nun also die Frage warum funktioniert es nicht im eigentlichen Projekt???

Hier mal ein wenig Code und Hintergrund:

Ich öffne die Datenbank so:
Delphi-Quellcode:
function TMasterDB.OpenCatalog(AOwner: TComponent; ACatalogName: Widestring): TCatalog;
begin
  Result := TCatalog.Create(AOwner, ACatalogName, '', False);

  if Assigned (Result) then
      FListedCatalogs.Add(Result); // TObjectlist (zur Verwaltung der Datenbankknoten im VST
                                   //(Anzeigeelemnent für DB und Datensätze)
end;
Definition TCatalog:
Delphi-Quellcode:
type
  TCatalog = class(TDataModule)
    ConDB: TZConnection;
  private
    fCatID : Cardinal; // MasterDB-ID
    fCatName : WideString; // Name (VST OnGetText)
    fCatDescr : Widestring; // Beschreibung (VST OnHint)
    procedure SetCatalogID(const Value: Cardinal);
    procedure SetCatalogName(const Value: Widestring);
    procedure SetCatalogDescr(const Value: Widestring);
    function CreateCatalog: Boolean;
  public
    property CatalogID: Cardinal read fCatID write SetCatalogID;
    property CatalogName: Widestring read fCatName write SetCatalogName;
    property CatalogDescr: Widestring read fCatDescr write SetCatalogDescr;

    constructor Create(AOwner: TComponent; AName: WideString; ADesc: WideString;
      New: Boolean = True); overload;
    destructor Destroy; override;

    function Open: Boolean;
    function Close: Boolean;
end;

{==============================================================================
  Datenbankverbindung herstellen (Vorhandene DB)
===============================================================================}

function TCatalog.Open: Boolean;
begin
  Result := False;
  // Katalog öffnen (verbinden)
  with conDB do
    try
      Database := pyPathes.DBPath + fCatName + pyCatDBExt;
      Connect;
      Result := Connected;
    finally
//
    end;
end;

{==============================================================================
  Datenbankverbindung schliessen
===============================================================================}

function TCatalog.Close: Boolean;
begin
  ConDB.Disconnect;
  Result := not ConDB.Connected;
end;

{==============================================================================
  Anlegen Neue DB
===============================================================================}

function TCatalog.CreateCatalog: Boolean;
var
  OK: Boolean;
begin
  Result := false;
  OK := False;
  // Katalog anlegen
  with conDB do
    try
      Database := pyPathes.DBPath + fCatName + pyCatDBExt;
      Connect;
      with TZQuery.Create(nil) do
        try
          Connection := conDB;
          // Tabelle Prog internas
          SQL.Add('CREATE TABLE [tblInternal] (');
          SQL.Add('[IntType] INTEGER NOT NULL DEFAULT 1,'); // MasterDB(0) oder Katalog(1) oder ReferenzDB(2)
          SQL.Add('[IntProgVersion] TEXT NOT NULL,'); // Erstellt mit Pythia Version
          SQL.Add('[IntDBVersion] TEXT NOT NULL,'); // Datenbankversion
          SQL.Add('[IntSQLVersion] TEXT NOT NULL,'); // Erstellt mit SQLite Version
          SQL.Add('[IntMagic] TEXT NOT NULL,'); // Magicnr der MasterDB (wird bei jedem ERZEUGEN der MasterDB neu angelegt)
          SQL.Add('[IntCatCreation] DATE NOT NULL,'); // Katalog erstellt am/um
          SQL.Add('[IntCatLastChange] DATE NOT NULL,'); // Letzte Änderungen im Katalog am/um
          SQL.Add('[IntCatDescr] TEXT NULL'); // Beschreibung des Katalogs
          SQL.Add(');');
          //
          // Erzeugung weiterer Tabellen
          //
          // Zeitpunkt der Erstellung und Versionsnr. eintragen
          SQL.Add('INSERT INTO tblInternal');
          SQL.Add('(IntProgVersion, IntDBVersion, IntSQLVersion, IntMagic, IntCatCreation, IntCatLastChange)');
          SQL.Add(' VALUES (:AVersion, :ADBVersion, :ASQLVersion, :AMNr, DATETIME(''now''), DATETIME(''now''));');
          ParamByName('AVersion').Value := pyVersion.ProgVersion;
          ParamByName('ADBVersion').Value := pyVersion.DBVersion;
          ParamByName('ASQLVersion').Value := pyVersion.SQLiteVersion;
          ParamByName('AMNr').Value := pyVersion.MagicNo;
          ExecSQL;
          OK := True;
        finally
          Free;
        end;
    finally // ConDB
      Disconnect;
    end;
    Result := OK; // Alles gut gelaufen
end;

{==============================================================================
  Erzeugen des Objektes und Anlegen des Katalogs
===============================================================================}

constructor TCatalog.Create(AOwner: TComponent; AName: WideString;
                            ADesc: WideString; New: Boolean);
begin
  inherited Create(AOwner);
  fCatName := AName;
  fCatDescr := ADesc;
  if not New then
    Open
  else begin
    CreateCatalog;
  end;
end;

destructor TCatalog.Destroy;
begin
  inherited Destroy;
end;
Hier die Routine zum Umbenennen:

Delphi-Quellcode:
function TMasterDB.RenameCatalog(ACatalog: TCatalog;
  ANewCatName: Widestring): Boolean;
var
  ACatID: Cardinal;
  fo, fn: WideString;
begin

  Result := False;

  fo := pyPathes.DBPath + ACatalog.CatalogName + pyCatDBExt;
  fn := pyPathes.DBPath + ANewCatName + pyCatDBExt;
  // Umbenennen nur möglich wenn Verbindung getrennt
  // (Öffnen erst wieder bei einer Aktion am Katalog)
  if ACatalog.Close then begin
    if WideRenameFile(fo, fn) then begin
      // Datei erfolgreich umbenannt => auch in MasterDB umbenennen?
      if RenameCatalogEntry(ACatalog.CatalogID, ANewCatName) then begin
        ACatalog.CatalogName := ANewCatName;
      end
      else
        WideRenameFile(fn, fo); // Umbenennen in MasterDB fehlgeschlagen -> zurück zum ursprünglichen Namen
    end;
  end;
end;
Die Datenbanken (Typ TCatalog) werden über eine Objektliste verwaltet. D.h. jedesmal wenn ein TCatalogObject erzeugt wird, wird es der Objektliste FlistedCatalogs hinzugefügt. Wie oben zu sehen ist, hat jedes TCatalog auch eine Eigenschaft CatalogName, die im VST zur Anzeige benutzt wird.

Vor der Umstellung gab es keine TObjectlist, sondern nur eine StringList mit den Namen der vorhandenen DB's. Die Daten für das VST, die nun aus dem Object TCatalog kommen, kamen vorher aus Record's.

Liegt vielleicht hier der Hase im Pfeffer begraben??? Klappt es wegen der Objectlist nicht??? Müsste nur 'ne Kleinigkeit am Code / Design umgestellt werden ???

Ach ja, es gibt noch eine MasterDB, in der die Namen und eine ID pro DB verwaltet werden. Aus diesem Modul kommt auch der Aufruf
Delphi-Quellcode:
RenameCatalog(ACatalog: TCatalog;
  ANewCatName: Widestring)
  Mit Zitat antworten Zitat
OG Karotte
(Gast)

n/a Beiträge
 
#10

Re: Datenbank per Code umbenennen

  Alt 12. Mai 2008, 17:44
Zitat von OG Karotte:
Stellt sich nun also die Frage warum funktioniert es nicht im eigentlichen Projekt???
Weil der Fehler ein Fehler zwischen den Kopfhörern war:

Wer eine DB "zweimal" öffnet sollte sie auch entspr. schliessen...

Daher: gelöst
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:38 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz