lunes, 30 de abril de 2007

Crear y restaurar copias de seguridad en C# con SQLExpress 2005.

Como comenzar. Bueno... en estos días he tenido que realizar un proyecto para realizar copias de seguridad de unas bases de datos, con lo que implica tambén crear un sistema de restauración.

En SQLServer existen unos objectos llamados jobs con los que podemos "decirle" a SQL que realice unas copias de seguridad, pero... en SQLExpress 2005 esta opción no existe.

Librerias a usar

Estas librerias se incluyen en referencias del proyecto en .NET:

using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;

Conexión al servidor

private Server GetServer() {
ServerConnection conn =

new ServerConnection("Serer", "user", "pass");
Server myServer = new Server(conn);
return myServer;
}

Backup Database

public void backupDB(object data) {
backupItem item = (backupItem)data;

if (changeDBEnv != null)
changeDBEnv(item.DbName, EventArgs.Empty);

Console.WriteLine("Backup the {0} database!", item.DbName);
Server myServer = GetServer();
Backup backup = new Backup();
backup.Action = BackupActionType.Database;
backup.Database = item.DbName;
item.BackupPath =

System.IO.Path.Combine(item.BackupPath, item.DbName + ".bak");
backup.Devices.Add(new BackupDeviceItem(item.BackupPath, DeviceType.File));
backup.Initialize = true;
backup.Checksum = true;
backup.ContinueAfterError = true;
backup.Incremental = false;
backup.LogTruncation = BackupTruncateLogType.Truncate;
backup.PercentComplete +=

new PercentCompleteEventHandler(backup_PercentComplete);
backup.Complete +=

new ServerMessageEventHandler(backup_Complete);
backup.SqlBackup(myServer);
}

Restore Database

public void RestoreDB(string file, string db) {
try {
Console.WriteLine("Restore the {0} database!", db);
if (changeDBEnv != null)
changeDBEnv(db, EventArgs.Empty);

Server myServer = GetServer();
Restore restore = new Restore();
restore.Action = RestoreActionType.Database;
restore.Database = db;
Database currentDb = myServer.Databases[db];
if (currentDb != null)
myServer.KillAllProcesses(db);
restore.Devices.AddDevice(file, DeviceType.File);
restore.ReplaceDatabase = true;
restore.PercentCompleteNotification = 10;
restore.PercentComplete +=

new PercentCompleteEventHandler(restore_PercentComplete);
restore.Complete +=

new ServerMessageEventHandler(restore_Complete);
Console.WriteLine("Restoring:{0}" + db);
restore.SqlRestore(myServer);
currentDb = myServer.Databases[db];
currentDb.SetOnline();
} catch(System.Data.SqlClient.SqlException e) {
log.WriteToLogAndConsole(e.Message);
}
}

Este código no funciona tal cual ya que faltan una serie de eventos que yo tenía. Simplemente hay que quitar lo que esta después de += incluidos estos y generarlos de nuevo.

Threading secuencial.

En estos días tuve un ligerillo problema con una aplicación que requeria una secuencia de acciones ejecutadas de forma secuencial pero en threads distintos. Aquí dejo un ejemplo que me hice y que me ayudo mucho:


using System;
using System.Threading;
using System.Collections.Generic;

namespace WindowsApplication1 {
class secuencialThread {
[STAThread]
static void Main(string[] args) {
threadSleep t = new threadSleep();
t.init();
}

}
public class threadSleep {
public Object esperaThread = "Que te esperes ...";
public Mutex firstMutex = new Mutex(false);
private Dictionary listadoThreads = new Dictionary();

public void init() {
this.listadoThreads.Add("Thread0", new Thread(new ParameterizedThreadStart(initThead)));
this.listadoThreads.Add("Thread1", new Thread(new ParameterizedThreadStart(initThead)));
this.listadoThreads.Add("Thread2", new Thread(new ParameterizedThreadStart(initThead)));
this.listadoThreads.Add("Thread3", new Thread(new ParameterizedThreadStart(initThead)));
this.listadoThreads.Add("Thread4", new Thread(new ParameterizedThreadStart(initThead)));

foreach (KeyValuePair item in this.listadoThreads) {
item.Value.Start(item.Key);
}
}

private void initThead(object data) {
lock (esperaThread) {
firstMutex.WaitOne();
Console.WriteLine("inicio de Thread --> " + (string)data);
for (int i = 0; i <= 5; i++) {
Console.WriteLine((string)data);
}
firstMutex.ReleaseMutex();
Console.WriteLine("Fin de Thread --> " + (string)data);
if ((string)data == "Thread4") {
Console.WriteLine("Fin de Threads" );
}

}
}
}
}

Esto produce como resultado:

inicio de thread Thread0 1,2,3,4,5 Fin de thread Thread0

inicio de thread Thread1 1,2,3,4,5 Fin de thread Thread1

inicio de thread Thread2 1,2,3,4,5 Fin de thread Thread2

inicio de thread Thread3 1,2,3,4,5 Fin de thread Thread3

inicio de thread Thread4 1,2,3,4,5 Fin de thread Thread4

Fin de Threads