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;

      }

    }

  }

}

 

Deployment of new database


Run application and press the Show scripts button. The application shows what scripts are to be executed in order to synchronize firmwareDevelop and firmware. As firmware is empty, synchronization results in the creation of two tables, primary keys and external key.

 

CREATE TABLE [dbo].[computer]([computer_id] INT NOT NULL IDENTITY(1,1),[name] NCHAR(100) COLLATE Cyrillic_General_CI_AS NULL )

 

CREATE TABLE [dbo].[software]([sofware_id] INT NOT NULL IDENTITY(1,1),[computer_id] INT NOT NULL ,[name] NCHAR(100) COLLATE Cyrillic_General_CI_AS NULL ,[version] INT NULL ,[serialKey] VARCHAR(30) COLLATE Cyrillic_General_CI_AS NULL ,[manufacturer] VARCHAR(100) COLLATE Cyrillic_General_CI_AS NULL )

 

ALTER TABLE [dbo].[computer] ADD CONSTRAINT [PK_computer] PRIMARY KEY CLUSTERED ([computer_id] ASC)  WITH(PAD_INDEX = OFF,IGNORE_DUP_KEY = OFF,STATISTICS_NORECOMPUTE = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON)

 

ALTER TABLE [dbo].[software] ADD CONSTRAINT [PK_software] PRIMARY KEY CLUSTERED ([sofware_id] ASC)  WITH(PAD_INDEX = OFF,IGNORE_DUP_KEY = OFF,STATISTICS_NORECOMPUTE = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON)

 

ALTER TABLE [dbo].[software] WITH CHECK ADD CONSTRAINT [FK_software_computer] FOREIGN KEY (computer_id) REFERENCES [dbo].[computer] (computer_id)  ON UPDATE NO ACTION ON DELETE NO ACTION

 

Adding new table



Initial database didn’t contain information on hardware. That is why a new hardware table related to the computer table is added to the model.


Figure 3: Database structure after the hardware table was added

Synchronization of databases is executed with the help of our application:


Figure 4: Synchronization of databases after hardware table was added

Set of commands executed to synchronize databases result in new hardware table with primary and external keys. The rest of database objects are the same; that is why no scripts to change them are generated.

Modification of the type of existing column

As you can see from the existing model, the field containing information about software version (software.version) is of int type; that is one of mistakes made when initial database was projected. Product versions can have identifiers containing not only figures but symbols as well. For example, SomeSoft 1 Beta 1 or SomeSoft 1.6 Pro. In order to save product version correctly, it is necessary to change field type, for example, to varchar(30).
One more problem end users will face with is inability to save software serial number, if its length is more than 30 symbols. I will extend the field to 2048 symbols.
Computer.name and software.name fields are of nchar type, while more optimal type is varchar.
As application has been in service, database was amplified with considerable amount of data; so it is necessary to avoid its repeated entering. SQL Schema Sync API always tries to execute casting whenever possible. Initial data is as follows:




Figure 5: Data stored in firmware before structure update


Figure 6: Modifications made to database

In order to change column types, the following scripts will be generated by the application:

 

ALTER TABLE [dbo].[software] DROP CONSTRAINT [FK_software_computer]

ALTER TABLE [dbo].[hardware] DROP CONSTRAINT [FK_hardware_computer]

ALTER TABLE [dbo].[software] DROP CONSTRAINT [PK_software]

 

ALTER TABLE [dbo].[computer] DROP CONSTRAINT [PK_computer]

ALTER TABLE [dbo].[computer] ADD TEMP_COLUMN VARCHAR(100) COLLATE Cyrillic_General_CI_AS NULL UPDATE [dbo].[computer] set TEMP_COLUMN = ([name])ALTER TABLE [dbo].[computer]

DROP COLUMN [name]

Execute sp_rename 'dbo.computer.TEMP_COLUMN','name','COLUMN'

 

ALTER TABLE [dbo].[software] ADD TEMP_COLUMN VARCHAR(100) COLLATE Cyrillic_General_CI_AS NULL UPDATE [dbo].[software] set TEMP_COLUMN = ([name])ALTER TABLE [dbo].[software]

DROP COLUMN [name]

Execute sp_rename 'dbo.software.TEMP_COLUMN','name','COLUMN'

 

ALTER TABLE [dbo].[software] ADD TEMP_COLUMN VARCHAR(30) COLLATE Cyrillic_General_CI_AS NULL UPDATE [dbo].[software] set TEMP_COLUMN = ([version])ALTER TABLE [dbo].[software]

DROP COLUMN [version]

Execute sp_rename 'dbo.software.TEMP_COLUMN','version','COLUMN'

 

ALTER TABLE [dbo].[software] ADD TEMP_COLUMN VARCHAR(2048) COLLATE Cyrillic_General_CI_AS NULL UPDATE [dbo].[software] set TEMP_COLUMN = ([serialKey])ALTER TABLE [dbo].[software]

DROP COLUMN [serialKey]

Execute sp_rename 'dbo.software.TEMP_COLUMN','serialKey','COLUMN'

 

ALTER TABLE [dbo].[computer] ADD CONSTRAINT [PK_computer] PRIMARY KEY CLUSTERED ([computer_id] ASC)  WITH(PAD_INDEX = OFF,IGNORE_DUP_KEY = OFF,STATISTICS_NORECOMPUTE = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON)

 

ALTER TABLE [dbo].[software] ADD CONSTRAINT [PK_software] PRIMARY KEY CLUSTERED ([sofware_id] ASC)  WITH(PAD_INDEX = OFF,IGNORE_DUP_KEY = OFF,STATISTICS_NORECOMPUTE = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON)

 

ALTER TABLE [dbo].[hardware] WITH CHECK ADD CONSTRAINT [FK_hardware_computer] FOREIGN KEY (computer_id) REFERENCES [dbo].[computer] (computer_id)  ON UPDATE NO ACTION ON DELETE NO ACTION

ALTER TABLE [dbo].[software] WITH CHECK ADD CONSTRAINT [FK_software_computer] FOREIGN KEY (computer_id) REFERENCES [dbo].[computer] (computer_id)  ON UPDATE NO ACTION ON DELETE NO ACTION

 

 


Data of columns which type was changed are saved. This was done owing to the fact that old types of data for columns were cast to new types.

Tools for complicated reorganization of database structure

In case of database refactoring database objects can be renamed. In this case, when database structure is synchronized object with the old name is deleted and object with a new name will be added. In most cases it doesn’t result in loss of data. If this is done with tables, it is necessary to transfer data from the old table to a new one. There are two events in DatabaseSync for this purpose: DatabaseUpdating and DatabaseUpdated. It is possible to copy data from the old table into temporary table in the DatabaseUpdating event handler, and transfer data from this temporary table to a new table in the DatabaseUpdated event handler. Executing manipulations with database will make you stay within a single transaction used to execute scripts generated by DatabaseSync. So, in case of unforeseen situation, rollback of transaction will be performed and changes made by the developer will be canceled as well. This helps keep database absolutely actual.

Let’s consider another sample with more complicated database modification.
It is not always possible to cast one type directly to the other. For example, it is not possible transfer data from image to varchar. In this case data will be lost. In order to avoid loss of data, you can use DatabaseUpdating/DatabaseUpdated mechanism again; this will allow transmission of data into temporary storage until database structure update is executed. After it is updated it is possible to fill new table with data using custom mechanism of data conversion.

I added adminPassword column of varchar(50) type to the computer table. Filled it with data and then cast it to bigint type so that column contains not password itself, but its hash-code.

Database synchronization is executed.

 

ALTER TABLE [dbo].[software] DROP CONSTRAINT [FK_software_computer]

ALTER TABLE [dbo].[hardware] DROP CONSTRAINT [FK_hardware_computer]

ALTER TABLE [dbo].[computer] DROP CONSTRAINT [PK_computer]

 

ALTER TABLE [dbo].[computer] ADD adminPassword VARCHAR(50) COLLATE Cyrillic_General_CI_AS NULL

 

ALTER TABLE [dbo].[computer] ADD CONSTRAINT [PK_computer] PRIMARY KEY CLUSTERED ([computer_id] ASC)  WITH(PAD_INDEX = OFF,IGNORE_DUP_KEY = OFF,STATISTICS_NORECOMPUTE = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON)

 

ALTER TABLE [dbo].[hardware] WITH CHECK ADD CONSTRAINT [FK_hardware_computer] FOREIGN KEY (computer_id) REFERENCES [dbo].[computer] (computer_id)  ON UPDATE NO ACTION ON DELETE NO ACTION

ALTER TABLE [dbo].[software] WITH CHECK ADD CONSTRAINT [FK_software_computer] FOREIGN KEY (computer_id) REFERENCES [dbo].[computer] (computer_id)  ON UPDATE NO ACTION ON DELETE NO ACTION

 


It is possible to cast password to its hash-code in several ways:
  1. conversion of password into convertible form (varchar bigint) is executed on server and password is saved in the same field;
  2. carry data from adminPassword to temporary table on the client side, and after database is synchronized conversion of password to its hash-code is executed;
  3. carry data from adminPassword to temporary table on server, and after database is synchronized conversion of password to its hash-code is executed.

We will consider all mentioned approaches.

1. In order to convert password from varchar to a type converted to bigint, it is necessary to execute the following steps:
  • subscribe for the DatabaseUpdating event and execute SQL command in its handler:

    update computer set adminPassword = cast(substring(hashbytes('SHA1', adminPassword), 1, 7) as bigint).



  • Execution of this command will result in writing hash-code instead of the password itself in the adminPassword field. As this field will actually contain number (written as string), it will be easily converted to bigint when database is synchronized.

    Realization:

     

    void databaseSync_DatabaseUpdating1(object sender, DatabaseUpdatingEventArgs e)

    {

      log.AppendLine("Database updating - begin");

      SqlCommand cmd = targetConnection.CreateCommand();

      cmd.Transaction = targetTransaction;

      cmd.CommandText = @"update computer set adminPassword =

        cast(substring(hashbytes('SHA1', adminPassword), 1, 7) as bigint)";

      log.AppendLine(cmd.CommandText);

      cmd.ExecuteNonQuery();

      log.AppendLine("Database updating - end");

  • Result of application work:

Database updating - begin

update computer set adminPassword = cast(substring(hashbytes('SHA1', adminPassword), 1, 7) as bigint)

Database updating - end

 

ALTER TABLE [dbo].[software] DROP CONSTRAINT [FK_software_computer]

ALTER TABLE [dbo].[hardware] DROP CONSTRAINT [FK_hardware_computer]

ALTER TABLE [dbo].[computer] DROP CONSTRAINT [PK_computer]

 

ALTER TABLE [dbo].[computer] ADD TEMP_COLUMN BIGINT NULL

UPDATE [dbo].[computer] set TEMP_COLUMN = ([adminPassword])

ALTER TABLE [dbo].[computer] DROP COLUMN [adminPassword]

Execute sp_rename 'dbo.computer.TEMP_COLUMN','adminPassword','COLUMN'

 

ALTER TABLE [dbo].[computer] ADD CONSTRAINT [PK_computer] PRIMARY KEY CLUSTERED ([computer_id] ASC)  WITH(PAD_INDEX = OFF,IGNORE_DUP_KEY = OFF,STATISTICS_NORECOMPUTE = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON)

ALTER TABLE [dbo].[hardware] WITH CHECK ADD CONSTRAINT [FK_hardware_computer] FOREIGN KEY (computer_id) REFERENCES [dbo].[computer] (computer_id)  ON UPDATE NO ACTION ON DELETE NO ACTION

ALTER TABLE [dbo].[software] WITH CHECK ADD CONSTRAINT [FK_software_computer] FOREIGN KEY (computer_id) REFERENCES [dbo].[computer] (computer_id)  ON UPDATE NO ACTION ON DELETE NO ACTION


2. If conversion is executed on the client side, it is necessary to do the following actions:
  • Retrieve data from adminPassword to a temporary table in the DatabaseUpdating event handler.
  • private DataTable tempTable = new DataTable();

     

    void databaseSync_DatabaseUpdating2(object sender, DatabaseUpdatingEventArgs e)

    {

      log.AppendLine("Database updating - begin");

      SqlDataAdapter adapter = new SqlDataAdapter(

        "SELECT computer_id, adminPassword FROM computer", targetConnection);

      adapter.SelectCommand.Transaction = targetTransaction;

      log.AppendLine(adapter.SelectCommand.CommandText);

      adapter.Fill(tempTable);

      SqlCommand cmd = new SqlCommand(

        "UPDATE computer SET adminPassword = NULL", targetConnection);

      cmd.Transaction = targetTransaction;

      log.AppendLine(cmd.CommandText);

      cmd.ExecuteNonQuery();

      log.AppendLine("Database updating - end");

    }

  • Execute update of rows in the computer table. Hash-code will be calculated for every row. GetHashCode() will be used for this purpose.

void databaseSync_DatabaseUpdated2(object sender, EventArgs e)

{

  SqlCommand cmd = targetConnection.CreateCommand();

  cmd.Transaction = targetTransaction;

  cmd.CommandText = @"UPDATE computer SET adminPassword = @adminPassword

    WHERE computer_id = @computer_id";

  cmd.Parameters.Add("@adminPassword", SqlDbType.Int);

  cmd.Parameters.Add("@computer_id", SqlDbType.Int);

  foreach (DataRow row in tempTable.Rows)

  {

    if (row["adminPassword"] == DBNull.Value)

      cmd.Parameters["@adminPassword"].Value = 0;

    else

      cmd.Parameters["@adminPassword"].Value = row["adminPassword"].GetHashCode();

    cmd.Parameters["@computer_id"].Value = row["computer_id"];

    cmd.ExecuteNonQuery();

  }

}


3. Necessary data from the computer table are carried to the temporary table on the server, and after database structure synchronization is executed, data from the temporary table converted to hash-code will be entered in the computer.adminPassword [bigint] field.
  • DatabaseUpdate event handler:
  • void databaseSync_DatabaseUpdating3(object sender, DatabaseUpdatingEventArgs e)

    {

      log.AppendLine("Database updating - begin");

      SqlCommand cmd = targetConnection.CreateCommand();

      cmd.Transaction = targetTransaction;

      cmd.CommandText = @"CREATE TABLE #tempTable (

        computer_id int, adminPassword varchar(50))";

      log.AppendLine(cmd.CommandText);

      cmd.ExecuteNonQuery();

     

      cmd.CommandText = "insert #tempTable select computer_id, adminPassword from computer";

      log.AppendLine(cmd.CommandText);

      cmd.ExecuteNonQuery();

     

      cmd.CommandText = "UPDATE computer SET adminPassword = NULL";

      log.AppendLine(cmd.CommandText);

      cmd.ExecuteNonQuery();

      log.AppendLine("Database updating - end");

    }

  • DatabaseUpdate event handler:
  • void databaseSync_DatabaseUpdated3(object sender, EventArgs e)

    {

      log.AppendLine("Database updated - begin");

      SqlCommand cmd = targetConnection.CreateCommand();

      cmd.Transaction = targetTransaction;

      cmd.CommandText = @"update computer set adminPassword =

      ( select top 1 cast(substring(hashbytes('SHA1', adminPassword), 1, 7) as bigint)

        from #tempTable where #tempTable.computer_id = computer.computer_id)";

      log.AppendLine(cmd.CommandText);

      cmd.ExecuteNonQuery();

      log.AppendLine("Database updated - end");

    }

  • Application work result:

Database updating - begin

CREATE TABLE #tempTable (computer_id int, adminPassword varchar(50))

insert #tempTable select computer_id, adminPassword from computer

UPDATE computer SET adminPassword = NULL

Database updating – end

 

ALTER TABLE [dbo].[software] DROP CONSTRAINT [FK_software_computer]

ALTER TABLE [dbo].[hardware] DROP CONSTRAINT [FK_hardware_computer]

ALTER TABLE [dbo].[computer] DROP CONSTRAINT [PK_computer]

 

ALTER TABLE [dbo].[computer] ADD TEMP_COLUMN BIGINT NULL

UPDATE [dbo].[computer] set TEMP_COLUMN = ([adminPassword])

ALTER TABLE [dbo].[computer] DROP COLUMN [adminPassword]

Execute sp_rename 'dbo.computer.TEMP_COLUMN','adminPassword','COLUMN'

 

ALTER TABLE [dbo].[computer] ADD CONSTRAINT [PK_computer] PRIMARY KEY CLUSTERED ([computer_id] ASC)  WITH(PAD_INDEX = OFF,IGNORE_DUP_KEY = OFF,STATISTICS_NORECOMPUTE = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON)

ALTER TABLE [dbo].[hardware] WITH CHECK ADD CONSTRAINT [FK_hardware_computer] FOREIGN KEY (computer_id) REFERENCES [dbo].[computer] (computer_id)  ON UPDATE NO ACTION ON DELETE NO ACTION

ALTER TABLE [dbo].[software] WITH CHECK ADD CONSTRAINT [FK_software_computer] FOREIGN KEY (computer_id) REFERENCES [dbo].[computer] (computer_id)  ON UPDATE NO ACTION ON DELETE NO ACTION

 

Database updated - begin

update computer set adminPassword =

      ( select top 1 cast(substring(hashbytes('SHA1', adminPassword), 1, 7) as bigint)

        from #tempTable where #tempTable.computer_id = computer.computer_id)

Database updated – end



One more advantage of handling DatabaseUpdating event is that reading of target database structure is executed before this event handler is invoked. This allows developers to add new tables to database, carry data from existing tables and to process data saved in temporary tables in the DatabaseUpdated event handler and write these data to the database of new structure. As temporary tables (or any other objects) will be added to database after database structure is read, table data (objects) won’t take part in synchronization and there is no need to add them to the list of skipped objects described in the next chapter. Moreover, execution of all manipulations within a single transaction guarantees restoration of data to the initial state when there is an error.

Skipping objects during synchronization

Often it is necessary to synchronize only some part of database objects. There is a special SkipSynchronizing event in DatabaseSync. You can easily subscribe to this event and skip some objects during database synchronization.

Suppose, developers need to store data connected to the other knowledge domain in the database described above. In order to detach objects required for new knowledge domain from existing ones it is logical to create a new schema for them. Name it SomeSchema. So, when you deliver update for FirmwareApp, it is natural database objects related only to this application are updated. That is why we need to skip objects located in SomeSchema in both client database and developers database.

To realize this algorithm of synchronization, it is necessary to subscribe for the SkipSynchronizing event and write in its handler the following code:

void sync_SkipSynchronizing(object sender, SkipSynchronizingEventArgs e)

{

  if (e.OldObject != null && e.OldObject is Schema &&

    (e.OldObject as Schema).Name.ToUpper() == "SomeSchema".ToUpper())

    e.NeedSynchronizing = false;

 

  if (e.NewObject != null && e.NewObject is Schema &&

    (e.NewObject as Schema).Name.ToUpper() == "SomeSchema".ToUpper())

    e.NeedSynchronizing = false;

 

  if (e.NewObject != null && e.NewObject is SchemaObject &&

    (e.NewObject as SchemaObject).Schema.Name.ToUpper() == "SomeSchema".ToUpper())

    e.NeedSynchronizing = false;

 

  if (e.OldObject != null && e.OldObject is SchemaObject &&

    (e.OldObject as SchemaObject).Schema.Name.ToUpper() == "SomeSchema".ToUpper())

    e.NeedSynchronizing = false;

}



There can be another approach to skipping objects: you can synchronize all objects from one schema and skip all other objects.

Resume

As you see from all written above, problem of database structure synchronization is a nontrivial task. There are various solutions, but practice shows that most of them are not quite satisfactory. Perpetuum Software offers solution that differs from all others.

In most cases synchronization of database structures is executed automatically. And only complicated cases require developer participation. This helps dramatically reduce time for the preparation and deployment of new application with updated database structure. In spite of the fact that synchronization is executed automatically, developers have the ability to control any action of this process.

Since SQL Schema Sync API is a set of components, not the final solution, you don’t need to install additional software on the client side, write patches or pay royalties for every copy of your application.

Download SQL Schema Sync API evaluation...

Visual Studio Partner


MS SQL 2008 schemas comparison utility
Microsoft Certified Partner

 USA

Phone: +1 (813) 514-0531

sales-usa@perpetuumsoft.com

 América Latina

Phone: +55 (11) 4618-0368

vendas@perpetuumsoft.com

 Europe

Phone: +49 (0) 6227 839-990

sales-europe@perpetuumsoft.com

 Russia

Phone: +7 (385) 236-0885

sales@perpetuumsoft.com


As a Gold Certified Partner in the Microsoft Partner program, Perpetuum Software has been providing a wide range of Microsoft Visual Studio components for over 8 years. Perpetuum Software product lines include WinForms, ASP.NET, Silverlight, and Mobile components, and tools for SQL Server Reporting Services. Among them are .NET reporting tool, OLAP component, and such data visualization libraries as gauge and charting products. All the products can be ordered via Share-It and PayPro services.