Question

I have a program on a computer and on a tablet. The program uses SQL Server Express to interact with a local database (the same information on both) from a .MDF file. So if I plug the tablet into the PC, I have two .MDF files that I want to synchronize.

I want both users to be able to make changes to the version on their device, then I want to get both .MDF files and run a script that merges them.

The database has a GUID primary key, and a DateTime of when it was last changed, so if there are conflicts, I would just take the most recent version.

How should I do this?

Or alternatively, if I'm going about this the wrong way, could you recommend an alternative way to keep the databases of these two machines synchronized without an internet connection?

Thanks in advance.

Was it helpful?

Solution 4

Most existing tools like Microsoft Sync and Merge-Replication ended seeming likebeing way too much overkill and being more hassle than they'd be worth.

This is my SQL Script to attach the databases

CREATE DATABASE LocalDatabase  
ON (Filename = 'C:\ProgramData\Clayton\Database.mdf')
   , (Filename = 'C:\ProgramData\Clayton\Database_log.ldf') 
FOR ATTACH;
GO

EXEC sp_addlinkedserver @server='Server'

Then to sync the databases

-- update the client from the master 
MERGE [LocalDatabase].[dbo].[tableName] trgt
using [Server].[ServerDatabase].[dbo].[tableName] src

ON trgt.id = src.id 

WHEN matched AND trgt.lastmodified <= src.lastmodified THEN 
  -- if the master has a row newer than the client
  -- update the client                       
  UPDATE SET trgt.[allColumns]      = src.[allColumns],
             trgt.[id]              = src.[id], 
             trgt.[lastmodified]    = src.[lastmodified] 

-- delete any rows added by a client 
WHEN NOT matched BY source 
THEN 
  DELETE 

-- insert any rows added by the master 
WHEN NOT matched BY target 
THEN 
  INSERT ( [allColumns], 
           [id], 
           [lastmodified]) 
  VALUES (src. [allColumns], 
          src.[id], 
          src.[lastmodified]); 


-- now we update the master from the client
-- Note:
-- because the serverDB is a linked server 
-- we can't use another MERGE statement, otherwise
-- we get the error: "The target of a MERGE statement 
-- cannot be a remote table, a remote view, or a view over remote tables."

UPDATE
    serverDB

SET 
    [allColumns]        = [localDB].[allColumns],
    [id]                = [localDB].[id], 
    [lastmodified]      = [localDB].[lastmodified] 

FROM 
     [Server].[ServerDatabase].[dbo].[tableName] serverDB

INNER JOIN
     [LocalDatabase].[dbo].[tableName] localDB

-- update where the id is the same but the client is newer than the master

ON serverDB.id = localDB.id 
       AND localDB.lastmodified >= serverDB.lastmodified

OTHER TIPS

Without an internet connection, you would be looking at merge or peer-to-peer replication. Neither of which can be implemented easily (google I seem to remember seeing a workaround somewhere) how you want with Express edition. If you had standard or better edition I would personally go with Peer-To-Peer as it negates the need for an additional column per table and like merge includes conflict resolution. Be advised though that in my opinion replication is a fairly finicky technology and requires intermediate DBA skills to implement and troubleshoot efficiently. Also be advised that once replication is implimented that no transaction can be cleared by a transaction log backup or checkpoint (depending on your recovery model) until it has been distributed to its subscriber. Depending on the duration and number of commands between syncs this will cause your transaction log to grow and potentially fill the disk. Obviously if the avilable disk space becomes full no new transactions can be written / updated in the DB.

With an internet connection I would definitely look at Azure to give you a single database which both devices can write to.

Obviously you can also look to pull and merge the data via powershell, SSIS, C# scripts or get a trial licence of RedGate data compare and kick off via a windows scheduled task (SQL Server agent is not available in express) and do the job which replication would do out of the box.

On a side note depending on your usage you might be able to get hold of developer edition SQL Server licence which is equal to enterprise.

Edit 1: peer to peer is an enterprise only feature in 2008r2 and 2012 at least, unlike merge which is available in standard

Since I know Powershell and VB much better than T-SQL, I would use one of those languages to pull new records from each database, loop through them, and insert them into the other database. The script would save a file that contained the timestamp of the last record from each database, which it would use the next time it ran to get the records newer than that date. ...or store the timestamp or the GUID from the last row synced somewhere in the database.

Your terminology of "merging .mdfs" may throw people off here because you aren't going to try to read the files directly and merge the differences. You're just going to query for new records in each database and insert them into the other.

You could approach this by various other methods--this is but one.

Take a look at existing technology: replication.

As per the documentation (emphasis added):

Replication is a set of technologies for copying and distributing data and database objects from one database to another and then synchronizing between databases to maintain consistency. Using replication, you can distribute data to different locations and to remote or mobile users.

Licensed under: CC-BY-SA with attribution
Not affiliated with dba.stackexchange
scroll top