Comparing a live database to a backup
From RedGateWiki
This example shows how a backup can be used as a data source in place of a live database. The backup file may be a native SQL Server (MTF) file, or a compressed and/or encrypted SQL Backup file. Note that the files and passwords are generic lists of type string. The reason for this is because BackupDatabaseSource can accept both full and differential backups, allowing you to retrieve the data in a point-in-time manner.
The data in the specified backup set is then compared to a live database and the differences are reported to the console.
C#
- using System;
- using System.Collections.Generic;
- using RedGate.BackupReader;
- using RedGate.Shared.Utils;
- using RedGate.SQLCompare.Engine;
- using RedGate.SQLCompare.Engine.ReadFromBackup;
- using RedGate.SQLDataCompare.Engine;
- using RedGate.SQLDataCompare.Engine.ResultsStore;
- using RedGate.Shared.SQL.BackupReaderInterfaces;
- namespace SQLDataCompareCodeSnippets
- {
- public class BackupComparisonExample
- {
- public void RunExample()
- {
- BackupSetDatabase backupDB = new BackupSetDatabase();
- Database liveDB = new Database();
- ComparisonSession session = new ComparisonSession();
- SchemaMappings mappings = new SchemaMappings();
- try
- {
- // First register the backup file
- Console.WriteLine("Registering backup");
- backupDB.Status += new StatusEventHandler(StatusCallBack);
- IList<string> files = new string[] { "c:\\widgetdev.bak" };
- IList<string> passwords = new List<string>();
- IList<IBackupSet> backupSets = backupDB.GetBackupSets(files, passwords);
- // use the latest backup set available
- IBackupSet backupSetToUse = backupSets[backupSets.Count - 1];
- BackupDatabaseSource backupDBSource = new BackupDatabaseSource(files, passwords, backupSetToUse);
- backupDB.RegisterForDataCompare(backupDBSource.ToConnectionProperties());
- // Secondly register the live database
- Console.WriteLine("Registering live database");
- liveDB.Status += new StatusEventHandler(StatusCallBack);
- liveDB.RegisterForDataCompare(new ConnectionProperties(".", "WidgetLive"), Options.Default);
- // Create the mappings between the two databases
- mappings.CreateMappings(backupDB, liveDB);
- session.CompareDatabases(backupDB, liveDB, mappings);
- foreach (TableMapping mapping in mappings.TableMappings)
- {
- TableDifference difference = session.TableDifferences[mapping.Obj1.FullyQualifiedName];
- // Any tables that couldn't be compared we don't output the results
- if (difference == null)
- continue;
- //loop through all the rows
- foreach (Row row in difference.ResultsStore)
- {
- //go through the non same records
- if (row.Type != Row.RowType.Same)
- {
- Console.WriteLine("{0} Row {1} type {2}", mapping.Obj1.FullyQualifiedName, row.Index, row.Type.ToString());
- int i = 0;
- foreach (FieldPair field in difference.ResultsStore.Fields)
- {
- int field1 = field.OrdinalInResults1;
- int field2 = field.OrdinalInResults2;
- if (field1 != field2)
- {
- // Get the values
- object value1 = row.Values[field1];
- object value2 = row.Values[field2];
- if (value1 == null)
- value1 = "NULL";
- if (value2 == null)
- value2 = "NULL";
- Console.WriteLine("{0}\t{1}\t{2}\t{3}", field.Field(false).Name, value1.ToString(), row.FieldDifferent(i) ? "<>" : "==", value2.ToString());
- }
- else
- {
- // This is part of the unique index we are comparing on
- object value = row.Values[field1];
- Console.WriteLine("*{0}\t{1}", field.Field(false).Name, value.ToString());
- }
- i++;
- }// End of foreach field pair
- }
- }// End of foreach row
- }// End of foreach mappings
- }
- finally
- {
- session.Dispose();
- backupDB.Dispose();
- liveDB.Dispose();
- }
- }
- private static void StatusCallBack(object sender, StatusEventArgs e)
- {
- if (e.Message != null)
- {
- Console.WriteLine(e.Message);
- }
- if (e.Percentage != -1)
- {
- Console.WriteLine("{0}%", e.Percentage);
- }
- }
- }
- }
VB
- Imports System
- Imports System.Collections.Generic
- Imports RedGate.BackupReader
- Imports RedGate.Shared.Utils
- Imports RedGate.SQLCompare.Engine
- Imports RedGate.SQLCompare.Engine.ReadFromBackup
- Imports RedGate.SQLDataCompare.Engine
- Imports RedGate.SQLDataCompare.Engine.ResultsStore
- Imports RedGate.Shared.SQL.BackupReaderInterfaces
- Module Module1
- Public Sub Main()
- Dim backupDB As New BackupSetDatabase()
- Dim liveDB As New Database()
- Dim session As New ComparisonSession()
- Dim mappings As New SchemaMappings()
- Try
- ' First register the backup file
- Console.WriteLine("Registering backup")
- backupDB.Status = New StatusEventHandler(AddressOf StatusCallBack)
- Dim files As IList(Of String) = New String() {"c:\widgetdev.bak"}
- Dim passwords As IList(Of String) = New List(Of String)()
- Dim backupSets As IList(Of IBackupSet) = backupDB.GetBackupSets(files, passwords)
- ' use the latest backup set available
- Dim backupSetToUse As IBackupSet = backupSets(backupSets.Count - 1)
- Dim backupDBSource As New BackupDatabaseSource(files, passwords, backupSetToUse)
- backupDB.RegisterForDataCompare(backupDBSource.ToConnectionProperties())
- ' Secondly register the live database
- Console.WriteLine("Registering live database")
- liveDB.Status = New StatusEventHandler(AddressOf StatusCallBack)
- liveDB.RegisterForDataCompare(New ConnectionProperties(".", "WidgetLive"), Options.[Default])
- ' Create the mappings between the two databases
- mappings.CreateMappings(backupDB, liveDB)
- session.CompareDatabases(backupDB, liveDB, mappings)
- For Each mapping As TableMapping In mappings.TableMappings
- Dim difference As TableDifference = session.TableDifferences(mapping.Obj1.FullyQualifiedName)
- ' Any tables that couldn't be compared we don't output the results
- If difference Is Nothing Then
- Continue For
- End If
- 'loop through all the rows
- For Each row__1 As Row In difference.ResultsStore
- 'go through the non same records
- If row__1.Type <> Row.RowType.Same Then
- Console.WriteLine("{0} Row {1} type {2}", mapping.Obj1.FullyQualifiedName, row__1.Index, row__1.Type.ToString())
- Dim i As Integer = 0
- For Each field As FieldPair In difference.ResultsStore.Fields
- Dim field1 As Integer = field.OrdinalInResults1
- Dim field2 As Integer = field.OrdinalInResults2
- If field1 <> field2 Then
- ' Get the values
- Dim value1 As Object = row__1.Values(field1)
- Dim value2 As Object = row__1.Values(field2)
- If value1 Is Nothing Then
- value1 = "NULL"
- End If
- If value2 Is Nothing Then
- value2 = "NULL"
- End If
- Console.WriteLine("{0}" & vbTab & "{1}" & vbTab & "{2}" & vbTab & "{3}", field.Field(False).Name, value1.ToString(), If(row__1.FieldDifferent(i), "<>", "=="), value2.ToString())
- Else
- ' This is part of the unique index we are comparing on
- Dim value As Object = row__1.Values(field1)
- Console.WriteLine("*{0}" & vbTab & "{1}", field.Field(False).Name, value.ToString())
- End If
- i += 1
- ' End of foreach field pair
- Next
- End If
- ' End of foreach row
- Next
- ' End of foreach mappings
- Next
- Finally
- session.Dispose()
- backupDB.Dispose()
- liveDB.Dispose()
- End Try
- End Sub
- Private Sub StatusCallBack(ByVal sender As Object, ByVal e As StatusEventArgs)
- If e.Message IsNot Nothing Then
- Console.WriteLine(e.Message)
- End If
- If e.Percentage <> -1 Then
- Console.WriteLine("{0}%", e.Percentage)
- End If
- End Sub
- End Module