Lately I've been busy maintaining old systems. The famous .NET 1.1 and alike.
While enjoying a bit of "retro" motion I also saw the giant leaps the new tools did. What impressed me most was the scripting of DB.
Just a few years ago I was in a need for DB structure copy, which would be in the form of a script. The reason for this is simple: automatic creation of the latest DB after the installation without the need for building a new setup script each time an object had changed.
I did the job by building a small utility which ran a "SELECT * FROM sysobjects" with the appropriate flags for tables, keys, procedures and all the other needful stuff.
Lately I needed that ability again, we did some changes to the DB but forgot what they where... So I thought here goes a "deja vue", do a 3 days work again in order to produce a utility like the old one. Luckily for me times changed and so I've found myself ending with a much simpler code:
System.IO.StreamWriter sw = new System.IO.StreamWriter("d:\\diffs.lst");
Microsoft.SqlServer.Management.Smo.Server sServer = new Microsoft.SqlServer.Management.Smo.Server("DBServer1");
Microsoft.SqlServer.Management.Smo.Database sDB = sServer.Databases["DB1"];
Microsoft.SqlServer.Management.Smo.Server dServer = new Microsoft.SqlServer.Management.Smo.Server("DBServer2");
Microsoft.SqlServer.Management.Smo.Database dDB = dServer.Databases["DB2"];
foreach (Microsoft.SqlServer.Management.Smo.Table tbl in sDB.Tables)
{
if (!tbl.IsSystemObject)
{
Console.WriteLine(tbl.Name);
if (dDB.Tables.Contains(tbl.Name))
{
Microsoft.SqlServer.Management.Smo.Table tbl2 = dDB.Tables[tbl.Name];
string scr1 = Decollect(tbl.Script());
string scr2 = Decollect(tbl2.Script());
if (scr1 != scr2)
{
sw.WriteLine(tbl.Name + " - differs");
}
}
else
{
sw.WriteLine(tbl.Name + " - missing");
}
}
else
{
Console.WriteLine("Skipping system table: " + tbl.Name);
}
}
foreach (Microsoft.SqlServer.Management.Smo.StoredProcedure sp in sDB.StoredProcedures)
{
if (!sp.IsSystemObject)
{
Console.WriteLine(sp.Name);
if (dDB.StoredProcedures.Contains(sp.Name))
{
Microsoft.SqlServer.Management.Smo.StoredProcedure sp2 = dDB.StoredProcedures[sp.Name];
string scr1 = Decollect(sp.Script());
string scr2 = Decollect(sp2.Script());
if (scr1 != scr2)
{
sw.WriteLine(sp.Name + " - differs");
}
}
else
{
sw.WriteLine(sp.Name + " - missing");
}
}
else
{
Console.WriteLine("Skipping system proc: " + sp.Name);
}
}
Plus a small helping function to convert the arrays (collections) to strings:
private static string Decollect(System.Collections.Specialized.StringCollection sc)
{
StringBuilder res = new StringBuilder();
foreach (string s in sc)
{
res.Append(s);
}
return res.ToString();
}
Now all I need is something to replace the old backup script:
Option Explicit
Const DB = "DB"
Const User = "sa"
Const Pass = "sa"
Const Server = "(local)"
Call Main()
Sub Main()
If WScript.Arguments.Count=1 Then
Call Restore(WScript.Arguments(0))
Else
Call Backup()
End If
End Sub
Function Restore(BackupFile)
Dim fso
Set fso = CreateObject("scripting.filesystemobject")
If Not fso.FolderExists("D:\backup") Then
fso.CreateFolder("D:\backup")
End If
Dim cmdFile
Set cmdFile = fso.CreateTextFile("c:\backup.sql",True)
cmdFile.WriteLine "DROP DATABASE " & DB
cmdFile.WriteLine "GO"
cmdFile.WriteLine "RESTORE DATABASE " & DB & " FROM DISK = '" & BackupFile & "'"
cmdFile.Close
Set cmdFile = Nothing
Call Exec("osql -U " & User & " -P " & Pass & " -S " & Server & " -i c:\backup.sql -o " & BackupFile & ".log")
Set fso = Nothing
End Function
Function Backup()
Dim BackupFile
BackupFile = "D:\backup\" & DB & DateAsString(Now()) & ".bak"
Dim fso
Set fso = CreateObject("scripting.filesystemobject")
If Not fso.FolderExists("D:\backup") Then
fso.CreateFolder("D:\backup")
End If
Dim cmdFile
Set cmdFile = fso.CreateTextFile("c:\backup.sql",True)
cmdFile.WriteLine "BACKUP DATABASE " & DB & " TO DISK = '" & BackupFile & "'"
cmdFile.Close
Set cmdFile = Nothing
Call Exec("osql -U " & User & " -P " & Pass & " -S " & Server & "-i c:\backup.sql -o " & BackupFile & ".log")
Set fso = Nothing
End function
Function Exec(pCommandLine)
On Error Resume Next
Dim WshShell : Set WshShell = WScript.CreateObject("WScript.Shell")
Exec = WshShell.Run(pCommandLine,,True)
If Err.number <> 0 Then
Exec = 255
Err.clear
End If
End Function
function DateAsString(ReqDate)
dim res
res = ""
res = res & year(ReqDate)
res = res & month(ReqDate)
res = res & day(ReqDate)
res = res & hour(ReqDate)
res = res & minute(ReqDate)
res = res & second(ReqDate)
DateAsString = res
end function
Sunday, June 13, 2010
Subscribe to:
Posts (Atom)