Search code examples
sql-serverado.netsql-server-2000data-synchronization

Synchronising SQL Server data via xml export


I need someone's expertise on the following:

I am building a web-facing system for a client which needs to sync 30-odd tables between it and their .NET 1.1 WinForms application. To minimise interaction between us for the sake of both of our sanity, I suggested using XML, like so

SELECT *
FROM table1
FOR XML AUTO, XMLDATA

The caveat is that I need the primary keys to remain the same between the source and destination DB's. Is there an elegant way of importing the XML? I don't want to write ugly SQL to drop and recreate tables and relationships each time there is a data sync. Is there a way via ADO.NET or Entity Framework 3 to tell the database "Look, here's your data, please use it instead of what you currently have"?

Here's an example of the exported XML:

<taxGroup>
   <Schema name="Schema29" xmlns="urn:schemas-microsoft-com:xml-data" xmlns:dt="urn:schemas-microsoft-com:datatypes">
      <ElementType name="taxGroup" content="empty" model="closed">
         <AttributeType name="taxGroupId" dt:type="i8"/>
         <AttributeType name="regionId" dt:type="i8"/>
         <AttributeType name="description" dt:type="string"/>
         <AttributeType name="percentage" dt:type="number"/>
         <AttributeType name="exportNumber" dt:type="string"/>
         <attribute type="taxGroupId"/>
         <attribute type="regionId"/>
         <attribute type="description"/>
         <attribute type="percentage"/>
         <attribute type="exportNumber"/>
      </ElementType>
   </Schema>
   <taxGroup xmlns="x-schema:#Schema29" taxGroupId="38000001" regionId="1482000001" description="VAT" percentage="0.1400" exportNumber=""/>
   <taxGroup xmlns="x-schema:#Schema29" taxGroupId="38000002" regionId="1482000001" description="VAT2" percentage="0.1700" exportNumber=""/>
</taxGroup> 

Note: the two DB's don't have access to one another. The transport is via Secure HTTPRequest.

Update 2: The Winforms app uses SQL2000, which makes using the Synch Framework impossible, apparently...

Update 3: Let's just take it as a given that I am stuck having to do things in this manner. The .NET app is deployed at various 3rd party sites, each having a separate copy of the DB and connecting to a separate instance of the web application. It's a reseller package, for all intents and purposes: a physical storefront component and an online store component. Some third parties refuse to upgrade from SQL2000.


Solution

  • Okay, so I took this problem to our MD, who was a system's architect in a previous life. He suggested I import the XML into a separate holding database with an identical structure. Before I add the data, I disable constraint checking and empty all the tables in staging:

    EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all";
    EXEC sp_msforeachtable "DELETE FROM ? ";
    EXEC sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all";
    

    I then import the XML into the staging DB by reading it into an ADO.NET DataSet and writing each row into the corresponding table in the DB. I can take lots of liberties because the source table has the exact same schema and plus the exported XML has the schema right there in the header, so everything is straightforward.

    I then execute a custom stored procedure on the target DB that first fires off

    EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all";
    

    then DELETEs everything from my target tables. I can't simply run [EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"] because there are extra tables in the target DB which would also be affected.

    I then simply do a

    SELECT INTO 
    

    from each table in staging to its duplicate in the target. Finally, I run

    EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all";
    

    To make sure every constraint is back the way it was.