Ostatnio miałem potrzebę zrobienia kopii bazy systemu, nad którym aktualnie pracuję. Docelowo chciałbym do wszystkich tabel dodać logowanie zmian, ale do tego czasu chciałem mieć czytelne migawki danych. Z tej racji, że baza źródłowa jest na razie dość mała, oraz ze względu na powszechność jako format docelowy wybrałem mdb, czyli bazę accessową.
Archiwizacja danych odbywa się w dwóch fazach:
- pobranie listy tabel przy użyciu metody GetSchema i ODBC,
- utworzenie w pętli tabel wynikowych za pomocą accessowej składni Select * Into TabelaWynikowa From TabelaZrodlowa IN '' [ODBC;CiagPolaczenia];
Kod nieco uproszczonej wersji:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Odbc;
using System.Data.OleDb;
namespace GdnKonsulting.BackupToMdbLogic
{
public class TransferData
{
private readonly string connectionString;
private readonly string schemaName;
private readonly string tmpFile;
private readonly string outputFileName;
public TransferData(string connectionString, string schemaName,
string outputFileName)
{
this.connectionString = connectionString;
this.schemaName = schemaName;
this.outputFileName = outputFileName;
this.tmpFile = System.IO.Path.GetTempFileName();
}
public void CreateDbAndTransferAllTables()
{
AdoxWorker.CreateDatabase(this.tmpFile);
List<string> tablesList = ReadTablesList();
ImportDataToDb(this.tmpFile, tablesList);
}
private List<string> ReadTablesList()
{
using (OdbcConnection connection = new OdbcConnection(connectionString))
{
connection.Open();
DataTable tables = connection.GetSchema("TABLES",
new string[] { null, schemaName });
List<string> result = new List<string>();
foreach (DataRow row in tables.Rows)
{
result.Add(tableName);
}
return result;
}
}
private void ImportDataToDb(string outputFileName, List<string> tablesList)
{
string connectionString = String.Format("Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source={0}", outputFileName);
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
OleDbCommand command = connection.CreateCommand();
connection.Open();
foreach (string tableName in tablesList)
{
string commandText = String.Format(
"Select * Into {0} From {1} IN '' [ODBC;{2}];",
tableName, tableName, this.connectionString);
command.CommandText = commandText;
command.ExecuteNonQuery();
}
}
}
}
}
I przykładowe wywołanie:
string connectionString = "Driver={Microsoft ODBC for Oracle};" +
"Server=ORCL;Uid=userName;Pwd=hasło;";
TransferData transfer = new TransferData(
connectionString, "userName", "C:\Backup.mdb");
W wersji produkcyjnej mam kilka ulepszeń:
- kompresję pliku accessowego.
- dodanie zdarzenia wywoływanego po udanym zapisie tabeli do pliku wyjściowego, by niezwłocznie informować o tym użytkownika,
- filtrowanie tabel (np. z oraclowych tabel znajdujących się w koszu, czyli o nazwach zaczynających się od "BIN$"),
- dodawanie do nazw tabel wynikowych nazwy schematu - na przewidywaną ewentualność importu danych z kilku schematów.
Aha, dodam jeszcze kod tworzący nowy plik mdb:
public static class AdoxWorker
{
public static void CreateDatabase(string fileName)
{
ADOX.CatalogClass cat = new ADOX.CatalogClass();
cat.Create("Provider=Microsoft.Jet.OLEDB.4.0;" +
"Data Source=" + fileName + ";" +
"Jet OLEDB:Engine Type=5");
}
}
Jak widać jest to wersja wymagająca wcześniejszego podłączenia bibliotek ADOX
To byłoby na tyle :).

0 komentarze:
Prześlij komentarz