Sync Guru Sync Guru
 
spacer
 
       
    Home
    Projects
    Articles
    Links
    About
 
   6087
  

  spacer

spacer
 
Synchronization Services for ADO.NET
   

 

Demo V: Offline Application - Oracle Backend
 
You might have noticed that the offline application we have been experimenting with in this demo series is always talking to SQL Server as the backend database. Now you ask: What If my backend database is not SQL Server? Am I going to write loads of code to achieve the same functionality that I get in few lines of code with SQL Server as a backend? After all, this a Microsoft technology and SQL Server is the database of choice, who cares about any other databases!? you think!.

Well, that is not the case. The sync services was designed with heterogeneous database support in mind. If you read into the API closely, you would notice that the server provider class is named as DbServerSyncProvider (eh, not SqlServerSyncProivder) which implies that it is for any database and not limited to SQL Server. As long as you have ADO.NET provider for the database of your choice, you are set to take advantage of Sync Services.

In this demo, I will change the offline application to talk to Oracle database. To keep things in focus and simplify the code, I will just implement a download only scenario for 'orders' table. However, you can implement all other features of the sync services against Oracle with same ease and control.

ADO.NET has a special data access provider for Oracle database which is what I am going to use in this demo. You could also use OLEDB or ODBC providers if you so choose.

The snapshot below shows the demo main form. Notice that I added a new text box for connection string such that you can connect to the Oracle database easily. I also added two buttons at the button of the form to create and delete the 'orders' table. The random insert, update and delete buttons are also there as shortcut to simplify manipulation of data on the Oracle database. Since this is a download only demo, these data manipulation buttons will be disabled when switching to the client database grid view.
 

 

As shown below, the code for the SyncAdapter is rather straight forward. I only need to set the commands for selecting incremental inserts, updates and deletes and that suffice for download only scenario:

// orders table
SyncAdapter adaptorOrders = new SyncAdapter("orders");               

// select incremental inserts command
OracleCommand incInsOrdersCmd = new OracleCommand();
incInsOrdersCmd.CommandType = CommandType.Text;
incInsOrdersCmd.CommandText = "SELECT id, col2, col3, col4 FROM orders " +   
                              "WHERE track_insert is null OR (  track_insert > :" +
                              SyncSession.SyncLastReceivedAnchor + " " +
                              "and track_insert <= :" + SyncSession.SyncNewReceivedAnchor + " )";

incInsOrdersCmd.Parameters.Add(":" + SyncSession.SyncLastReceivedAnchor, OracleType.Timestamp);
incInsOrdersCmd.Parameters.Add(":" + SyncSession.SyncNewReceivedAnchor, OracleType.Timestamp;    adaptorOrders.SelectIncrementalInsertsCommand = incInsOrdersCmd;

// select incremental updates command
OracleCommand incUpdOrdersCmd = (OracleCommand)incInsOrdersCmd.Clone();                incUpdOrdersCmd.CommandText = "SELECT id, col2, col3, col4 FROM orders " +                                      "WHERE (track_update > :"+SyncSession.SyncLastReceivedAnchor+") " +
                              "and (track_update <= :"+SyncSession.SyncNewReceivedAnchor+") " +
                              "and (track_insert <= :"+SyncSession.SyncLastReceivedAnchor+") ";
incUpdOrdersCmd.Parameters.Add(":" + SyncSession.SyncLastReceivedAnchor, OracleType.Timestamp);
incUpdOrdersCmd.Parameters.Add(":" + SyncSession.SyncNewReceivedAnchor, OracleType.Timestamp);
adaptorOrders.SelectIncrementalUpdatesCommand = incUpdOrdersCmd;

serverSyncProvider.SyncAdapters.Add(adaptorOrders);            
 

If there is one thing I want to stress on in this demo, other than the ability to use SyncServerProvider for heterogeneous backend, is the type mapping between the server database and the client database. Oracle database has different type system than that of SqlCe which is the client store.  To illustrate this point, I used different table schema for 'orders' table with different data type for each column.

Now, if you try to run the application it will fail  to create the schema on the client. Basically the schema information retrieved from the Oracle server database is not enough for SqlCe to create the orders table. In order to fix that, I need to abandon the automatic schema retrieval logic that the server provider uses and instead supply a SyncSchema object to the provider with all mapping information. The code below shows how I did that for the first 3 columns:

//
// 5. Custom Schema
//

SyncSchema syncSchema = new SyncSchema();
serverSyncProvider.Schema = syncSchema;

syncSchema.Tables.Add("orders");

syncSchema.Tables["orders"].Columns.Add("id");
syncSchema.Tables["orders"].Columns["id"].AllowNull = false;
syncSchema.Tables["orders"].Columns["id"].ProviderDataType = "NUMERIC";
syncSchema.Tables["orders"].Columns["id"].NumericPrecision = 5;
syncSchema.Tables["orders"].Columns["id"].NumericScale = 0;
syncSchema.Tables["orders"].PrimaryKey = new string[] { "id" }; 

syncSchema.Tables["orders"].Columns.Add("col2");
syncSchema.Tables["orders"].Columns["col2"].ProviderDataType = "CHAR";
syncSchema.Tables["orders"].Columns["col2"].MaxLength = 40; 

syncSchema.Tables["orders"].Columns.Add("col3");
syncSchema.Tables["orders"].Columns["col3"].DataType = typeof(String);
syncSchema.Tables["orders"].Columns["col3"].MaxLength = 32;

syncSchema.Tables["orders"].Columns.Add("col4");
syncSchema.Tables["orders"].Columns["col4"].ProviderDataType = "NUMERIC";
syncSchema.Tables["orders"].Columns["col4"].NumericPrecision = 38;
syncSchema.Tables["orders"].Columns["col4"].NumericScale = 0;

The rest of the columns can be mapped similarly.

If you inspected the auto generated schema by the provider, you would notice that the NumericPrecision and NumericScale values are not set which is why the client fails to use it. The ability to author the schema and pass it to the server provider gives you control on how the tables are set on the client regardless of backend data store. This is such a powerful feature and will allow you to build custom server providers for none database backbends.

Enjoy!
 

Install OfflineAppDemo Application Steps:

Version 1.2 [C#]: Download Now
 


 
     
 
Revision History

     January 26, 2007 - Initial release based on CTP1
     May 16, 2007 - Minor updates for beta 1.0 release
     August 17, 2007 - Update for beta 2.0 release
     November 26, 2007 - Update for RTM

Resources

     Download Synchronization Services for ADO.NET V1 RTM
     Contact me through my blog 
     Communicate feedback through the MSDN forum 
 
 
 
  
 

Copyright © 2007  -  Rafik Robeal
 All Rights Reserved