Automatic synchronization of two database schemas
Introduction
Description of the problem
Possible solutions of database structure synchronization problem
Perpetuum Software LLC offers a new solution!
Example of using SQL Schema Sync API
Deployment of new database
Adding new table
Modification of the type of existing column
Tools for complicated reorganization of database structure
Skipping objects during synchronization
Resume
Attachment: Firmware application. (Sample solution created to demonstrate automatic synchronization of database structures).
Introduction
Making changes to database structure
is one of the most time-consuming and routine operations developer of corporate
solutions faces with. In case of frequent updates, schedule time of the project
can be significantly extended. Existing tools solve this problem partially, as in
most cases they require manual programming and installation of expensive software
to synchronize database schemas on the client side or to make special patches for
every modification of database structure.
Description of the problem
Requirement of modern software
development methodologies (Extreme programming in particular) is to put software
into operation as fast as possible. Such approach presupposes improvement of applications
at their run-time. So, if you use databases, developer database structure often
differs from that of application end user, as developer regularly extends and modifies
source structure. In order to make current version of application run correctly,
it is necessary to have equal developer and client database structures. This problem
has some solutions, but performance of such solutions is often very poor.
Possible solutions of database structure synchronization
problem
We won’t consider variant of deleting
database on the client side and creating new one with the structure equal to developer
database, as this variant is not acceptable.
At the first sight, the simplest
variant is to form a set of SQL commands that should be executed to get database
into shape. This approach as all others has its advantages and disadvantages. Cheapness
of this variant can be conventionally labeled as advantage (conventionally, as everything
depends on amount of modifications made by the developer). But this approach has
a lot of disadvantages: - If there are a lot of changes, developer will spend a lot of time to form a set
of SQL commands;
-
There is a risk of incomplete synchronization of database structures, as commands
are formed manually, and human factor still stands;
-
Upgrade from one version to another requires accurate execution of all sets of commands
to upgrade to all intermediate database versions in the necessary order.
As you see, this approach supposes
quite high developer’s labour requirement, and at the same time developer and his
client can not be absolutely sure that synchronization is executed in the proper
way.
The other and more acceptable
variant is to use special tools. The following actions should be performed:-
Purchasing third-party tool or in-house development of such tool;
- Installing this tool on every customer computer;
-
Synchronization of database using this instrument.
This approach eliminates virtually
all disadvantages of the first method, but it has its own ones:-
Ready-made solutions are quite expensive. In-house development of such solution
is even more expensive;
-
Installation of the tool on the client side requires payment of royalties;
-
Developer has to deliver third-party tools together with his software;
-
Very often it is not possible to use such tools programmatically, so, intervention
of a developer responsible for installation of the update on the client side is
required. And this in its turn requires developers to train how to work with the
tool.
As you see from characteristics
of this method, it solves the task, but is too expensive and doesn’t exclude participation
of developers when new database version is deployed.
It is possible to use joint variant.
I.e. set of SQL commands required for synchronization will be generated by the third-party
tool, and then these commands will be executed on the target database without using
the tool which created them and without developer participation (patch). This approach
doesn’t save developer from some limitations. As before he needs to execute all
patches in strict sequence, cost of the tool is high, manual tweaking of scripts
is not excluded.
Perpetuum Software LLC released
a new product designed to synchronize structures of two databases – SQL Schema Sync API. Concept of the product is quite
different from those mentioned above. SQL Schema Sync API is a set of .Net components
which use allows the creation of applications of any type (WinForms, ASP.NET, Console,
WPF) that realize synchronization of database structures on MS SQL Server 2005/2008.
This approach has the following competitive advantages:
- No need to
use third-party tools;
- No need to
pay royalties for every copy of the product developed with the use of SQL Schema Sync API;
- The product
is easy to use; it features minimal set of settings, availability of complete product
documentation and class reference integrated into MSDN;
- Time necessary
to create and deploy new version of database is dramatically reduced. The product
saves both developer and client time.
Example of using SQL Schema Sync API
Product application field is too
wide, and we won’t describe all ways as it will take much time. We will consider
only basic approaches, and list all approaches at the end of the article.
We will consider real situation
as a demonstrating sample and will try to solve it using SQL Schema Sync API.
Suppose, some organization decides
to create a small application to register all software installed on the computers.
Storage of hardware description should also be included. Database on MS SQL Server
2005/2008 is used as data storage. Realization of the product, logic of its work and
interface are not so important. We are interested in evolution of database structure
in the process of application development and testing of the product and in the
problems developer faces with.
The following database structure
is used for the first test version of the application:
Figure 1: Initial database structure
It is obvious that it is projected
incorrectly; this is done specially to demonstrate modification of database structure
in the process of application development. I created two databases on SQL Server
and named them firmwareDevelop and firmware. Tables pictured in the Figure 1 are
created in the firmwareDevelop.
Create a simple WinForms application
(name it FirmwareApp) that will use DatabaseSync component ( )
delivered with SQL Schema Sync API. The main form will display names of databases that
will be synchronized.
Figure 2: Application appearance
The following code will execute
displaying scripts required for synchronization and synchronization itself.
C#
using
System;
using
System.Data;
using
System.Text;
using
System.Data.SqlClient;
using
PerpetuumSoft.DataModel;
using
PerpetuumSoft.DataModel.MsSql;
using
PerpetuumSoft.DataModel.MsSql.Synchronizers;
namespace
FirmwareApp
{
public
partial class
MainForm : System.Windows.Forms.Form
{
public
MainForm()
{
InitializeComponent();
}
private
StringBuilder log =
new StringBuilder();
private
SqlConnection targetConnection;
private
SqlTransaction targetTransaction;
private
string GetConnectionString(string
serverName, string databaseName)
{
SqlConnectionStringBuilder sourceConnStr = new
SqlConnectionStringBuilder(
@"Integrated Security=True;Connect Timeout=30;User Instance=False;");
sourceConnStr.DataSource =
serverName;
sourceConnStr.InitialCatalog
= databaseName;
return
sourceConnStr.ConnectionString;
}
private
void MainForm_Load(object
sender, EventArgs e)
{
databaseSync.ScriptExecuting
+=
new EventHandler<ScriptExecuteEventArgs>(databaseSync_ScriptExecuting);
}
void
databaseSync_ScriptExecuting(object sender,
PerpetuumSoft.DataModel.ScriptExecuteEventArgs e)
{
log.AppendLine(e.Text);
log.AppendLine();
}
private
void synchronizeButton_Click(object
sender, EventArgs e)
{
log =
new StringBuilder();
try
{
targetConnection =
new SqlConnection(
GetConnectionString(targetServerTextBox.Text,
targetDbTextBox.Text));
targetConnection.Open();
targetTransaction =
targetConnection.BeginTransaction();
try
{
Database database = databaseSync.ReverseDatabase(
GetConnectionString(sourceServerTextBox.Text,
sourceDbTextBox.Text));
databaseSync.UpdateDatabase(database,
targetConnection, targetTransaction);
targetTransaction.Commit();
logTextBox.Text
= log.ToString();
}
catch (Exception ex)
{
targetTransaction.Rollback();
logTextBox.Text
= log.ToString();
logTextBox.Text
+= ex.Message;
}
finally
{
targetConnection.Close();
}
}
catch
(Exception ex)
{
logTextBox.Text = log.ToString();
logTextBox.Text +=
ex.Message;
}
}
}
}
|