You are on page 1of 57

Distributed Geodatabase Development

(Best Practices)

Khaled Hassen
Gary MacDougall
Schedule

• 75 minute session
– 60 – 65 minute lecture
– 10 – 15 minutes Q & A following the lecture
• Cell phones and pagers

• Please complete the session survey – we take your


feedback very seriously!
Prerequisites

• Prerequisites
– Understand versioning
– Have reviewed the geodatabase replication on-line help and
developer documentation
• All code examples and demos are in C#
Overview

• Distributed geodatabase use cases and techniques


• Geodatabase replication
– Replication introduction
– Replication internals and developer API
– DEMO: Replica creation with custom workspace extension
• Interoperability with non-geodatabase formats
Distributed Geodatabase Use Cases

• Mobile Users and Field Crews who need to be


disconnected from the network

• Users who need to maintain copies of data at different


organizational levels (city, county, state)

• Users who want to maintain copies of data at different


geographic facilities

• Users who need to distribute work to contractors

• Production and publication geodatabases


Distributed Geodatabase Use Cases

Regional Offices Mobile Users

Office Office

Office Parent Office

Office Office

Production / Publication
Multiple levels
Main Office

Editors Readers

ArcGIS
Regional Regional Regional ArcIMS
Office Office Office Server

Local Local Local Local Local Local Local Local Local


Office Office Office Office Office Office Office Office Office
Production Publication
Geodatabase Geodatabase
Data Copying and Loading

• Involves simply using data copying and export/import


tools to copy data from one geodatabse to another
• Works well for systems with simple requirements
– Example: A field worker updates a feature class and simply
needs to copy that feature class to the ArcSDE geodatabase in
the office each night
• Limitations
– No safeguard against data lose
– No safeguards against data redundancy
DBMS Replication with Geodatabases

• Requirements and limitations


– Requires knowledge of how the geodatabase\ArcSDE system
tables work
– No tools provided in ArcGIS to support it
– Limited support for cross DBMS replication
– Does not support or has limited support for complex
geodatabase data types and limited filters to define the data to
replicate
• Advantages
– Can work with non-versioned data
– Can replicate entire database
– Can be configured to provide synchronous replication
Geodatabase Replication

• Allows you to distribute copies of data across 2 or more


geodatabases

• You can edit the databases independently and


synchronize them as needed

• Uses geodatabase connections directly (LAN) or using


geodata services publish on ArcGIS server (WAN)

• Works in a connected and a disconnected environment

• Can replicate subsets and uses versioning

• Released at 9.2 - Builds upon disconnected editing from


earlier releases (8.3)
Geodata Services: replica types

edits
Checkout/ Child
Parent
check-in geodatabase geodatabase
Once only

edits

One-way Parent Child


geodatabase Multiple times geodatabase

edits
Two-way Parent Child
geodatabase Multiple times geodatabase
Geodatabase Replication Workflows

• Workflows can involve


Multi-User geodatabases
Multi-user to Multi-user
and single user
geodatabases
– Multi-user geodatabase –
Enterprise Enterprise
Multi-user ArcSDE
geodatabase accessed
locally or remotely through
Multi-user to Single User
ArcGIS server

– Single user geodatabase –


Personal ArcSDE, file
Enterprise Personal Geodatabase,
geodatabase or personal File Geodatabase or
geodatabase on a local Peronal ArcSDE

machine
Data distribution in
Enterprise systems

• Geodata services can be used


in conjunction with other data Main
office
distribution techniques
• Scenario
– Use geodatabase replication to Region
office
synchronize changes between
offices
– Use Mobile services for field Web
services
workers with lightweight mobile
devices
– Use geodata services for field
workers who need ArcGIS Desktop
or ArcGIS Engine in the field

A
9.3 Geodatabase Replication

• Feedback from many clients


• Improve quality
– Added many bug fixes and enhancements to improve quality
and performance
– Added logging to improve trouble shooting
– Added white paper
• Enhancements based on feedback from clients
implementing replication
– Enhanced one way replication to support replicating to file
geodatabases and personal geodatabases
– User defined globalids (API)
– Make it easier to generate updategrams (API)
Geodatabase Replication – Getting Started

• Anticipate future needs when defining the data to


replicate
• Have a well defined data model before creating replicas
• Choose the right replica type
– Consider 2 way replicas with personal ArcSDE instead of check-
out replicas
– Use 1 way replicas over 2 way replicas when possible
Geodatabase Replication – Getting Started

• Use models or scripts for replicas you plan to create on


a regular basis
– You can use the create replica and create replica from server
geoprocessing tools to build models
• Consider using the following replica creation options
– Re-use schema (check-out replicas) – uses existing schema
– Register only – replicates pre-copied data
– Relationship classes processing is optional
• Schedule Synchronizations
– You can use geoprocessing models exported to python and the
windows scheduler
– Consider synchronization order
Geodatabase Replication – Getting Started

• Integrate synchronization with version management


strategy
– Synchronize before running reconcile and compress services
– Reconcile service should cover replicas with a manual reconcile
policy
• Network speed
– Use geodatabases directly over fast networks (LAN)
– Use ArcGIS server and geodata services on slower networks
(WAN – i.e. DSL)
– Use disconnected synchronization techniques over very slow
networks (slow dial-up modem) or where there is no network
connectivity
When to write code

• Basic creation and synchronizations using geoprocessing models


require little or no coding
• Write code when…
– Integrate geodatabase replication into larger applications
• Example: integrate synchronization with reconcile service
– Extend the replica creation and synchronization process
– Methods and properties not exposed through the UI or geoprocessing
tools
• Recommended synchronization order
• Browse changes before synchronization
• Advanced replica creation options
• Export and Import version differences
Geodatabase Replication – API

• GeoDatabaseDistributed library
• Coarse Grained API (Recommended)
• GeoDataServer Object Model – new at ArcGIS 9.2
• Stateless object model
• Geodatabase replication, browsing, querying, data
extraction
• Fine grained API
• Pre-ArcGIS 9.2 object models
– Data Extraction and Check out/Check in Object Model, XML Export and
Import Object Model
• Object models for specialized operations such as
browsing the contents of a delta file
– Data Changes Object Model, Schema Change Export and Import Object
Model
Geodatabase Replication – API

Geodatabase Distributed
Library

Internet
Coarse Grained API Remote
(GeoDataServer object model) Geodatabase

Lo
ca
l
Fine Grained API
(Data Extraction Check out/
Check in object model; XML
Export and Import Object Local Local
Model; Data Changes Object Geodatabase
Model; Schema Change
Export and Import Object
Model)
Supports Connected and Disconnected
Environments
• Connected
– All replicas accessible on the network (LAN or WAN)
– Always connected or intermittently connected
• Example: to synchronize, use the synchronize wizard in
ArcCatalog
• Disconnected
– Replicas are not on the same network
– Message exchange is performed by the end user
– Operations are performed by export, file transfer and import
• Example: to synchronize, export changes to a delta XML file,
transfer the file (ftp, CD through the mail, etc.), have the file
imported on the relative replica when it arrives, send
acknowledgement message back to sender
Connected and Disconnected Environments
Connected Disconnected
LAN LAN
XML XML
ReplicationAgent

GeoDataServer1 GeoDataServer2 GeoDataServer1 GeoDataServer2

Geodatabase Geodatabase Geodatabase Geodatabase

WAN (ArcGIS Server) WAN (ArcGIS Server)


XML XML
ReplicationAgent

GeoDataServer1 GeoDataServer2 GeoDataServer1 GeoDataServer2


(proxy) (proxy) (proxy) (proxy)

Internet Internet Internet Internet

GeoDataServer1 GeoDataServer2 GeoDataServer1 GeoDataServer2

Geodatabase Geodatabase Geodatabase Geodatabase


Geodatabase Replication API

• Replica creation

• Replica synchronization

• Replication extensibility

• Optimization, performance and best practice


Example: Create Replica in a Connected
Environment

• Steps
n Initialize a GeoDataServer for the source and target
geodatabases
o Create a GPReplicaDescription to define the data to be
replicate from the source
p Use the GPReplicaOptionsClass to define replica options
such as the replica type
q Use the ReplicationAgent to create the replica
Initializing GeoDataServers

n GeoDataServers represent local or remote geodatabases


– Local geodatabases are initialized directly
– Remote geodatabases are accessed from geodata services
published by ArcGIS server on the internet
Initializing from a local geodatabase
IGeoDataServer
IGeoDataServer iGDS
iGDS == new
new GeoDataServerClass();
GeoDataServerClass();
IGeoDataServerInit
IGeoDataServerInit iGDSInit
iGDSInit == iGDS
iGDS as
as IGeoDataServerInit;
IGeoDataServerInit;
iGDSInit.InitFromConnectionString("SERVER=bobmk;INSTANCE=5151;
iGDSInit.InitFromConnectionString("SERVER=bobmk;INSTANCE=5151;
VERSION=sde.DEFAULT;USER=gdb;PASSWORD=gdb");
VERSION=sde.DEFAULT;USER=gdb;PASSWORD=gdb");

Accessing a geodata service on the internet


IPropertySet
IPropertySet iCProps
iCProps == new
new PropertySetClass();
PropertySetClass();
iCProps.SetProperty("URL",@"http://baza/arcgis/services");
iCProps.SetProperty("URL",@"http://baza/arcgis/services");
IAGSServerConnectionFactory
IAGSServerConnectionFactory iSCF
iSCF == new
new AGSServerConnectionFactoryClass();
AGSServerConnectionFactoryClass();
IAGSServerConnection
IAGSServerConnection iSvrConn = iSCF.Open(iCProps, 0);
iSvrConn = iSCF.Open(iCProps, 0);
IAGSServerObjectName
IAGSServerObjectName iSObjName
iSObjName == null;
null;
While
While ((iSObjName
((iSObjName == iSvrConn.Next())
iSvrConn.Next()) !=!= null)
null) {{
if
if (iSObjName.Name
(iSObjName.Name ==
== “Sample_GeoDataService")
“Sample_GeoDataService") return
return iSObjName;
iSObjName; }}
Define the data to be replicated
o Create a GPReplicaDescription to define the data to
be replicated
public
public IGPReplicaDescription
IGPReplicaDescription CreateReplicaDescription(IGeoDataServer
CreateReplicaDescription(IGeoDataServer iGDS)
iGDS)
{{
IGPReplicaDescription
IGPReplicaDescription iGPRDescripton
iGPRDescripton == new
new GPReplicaDescriptionClass();
GPReplicaDescriptionClass();
IGPReplicaDatasets
IGPReplicaDatasets iGPRDatasets
iGPRDatasets == new
new GPReplicaDatasetsClass();
GPReplicaDatasetsClass();
IGPReplicaDataset
IGPReplicaDataset iGPRDataset
iGPRDataset == new
new GPReplicaDatasetClass();
GPReplicaDatasetClass();
iGPRDataset.Name == “Roads”;
iGPRDataset.Name iGPRDataset.Type == “esriDTFeatureClass”;
“Roads”; iGPRDataset.Type “esriDTFeatureClass”;
iGPRDatasets.Add(iGPRDataset);
iGPRDatasets.Add(iGPRDataset);

try
try {{
IGPReplicaDatasets
IGPReplicaDatasets iERDatasets
iERDatasets ==
iGDS.ExpandReplicaDatasets(iGPRDatasets);
iGDS.ExpandReplicaDatasets(iGPRDatasets);
}}
catch
catch (Exception
(Exception e)
e) {{ return
return null;
null; }}
iGPRDescription.GPReplicaDatasets
iGPRDescription.GPReplicaDatasets == iERDatasets;
iERDatasets;
iGPRDescription.SingleGeneration(false);
iGPRDescription.SingleGeneration(false);
……
return
return iGPRDescription;
iGPRDescription;
}}
Set the replica options
p Use the GPReplicaOptionsClass to define replica
options such as the replica type

//
// Set
Set the
the replica
replica options
options
IGPReplicaOptions
IGPReplicaOptions iReplicaOptions
iReplicaOptions == new
new GPReplicaOptionsClass();
GPReplicaOptionsClass();

//
// Set
Set type
type to
to 22 way
way replica
replica
iReplicaOptions.AccessType
iReplicaOptions.AccessType == esriReplicaAccessType.esriReplicaBothReadWrite;
esriReplicaAccessType.esriReplicaBothReadWrite;

//
// Important
Important only
only for
for replicas
replicas in
in disconnected
disconnected environments
environments
iReplicaOptions.IsChildFirstSender
iReplicaOptions.IsChildFirstSender == true;true;

//
// Copy
Copy the
the data
data during
during creation
creation
iReplicaOptions.RegisterReplicaOnly
iReplicaOptions.RegisterReplicaOnly == false;
false;
Create the replica

q Create the replica using the ReplicationAgent


CreateReplicaConnected(iGDSParent,
CreateReplicaConnected(iGDSParent, iGDSChild,
iGDSChild, iRepDescription,
iRepDescription,
iReplicaOptions)
iReplicaOptions)
……
public
public void
void CreateReplicaConnected(IGeoDataServer
CreateReplicaConnected(IGeoDataServer iGDSParent,
iGDSParent, IGeoDataServer
IGeoDataServer
iGDSChild,
iGDSChild, IGPReplicaDescription iRepDesc, IGPReplicaOptions iRepOptions)
IGPReplicaDescription iRepDesc, IGPReplicaOptions iRepOptions)
{{
String
String rVersion
rVersion == “MyWork”,
“MyWork”,
rName
rName == “MyReplica;
“MyReplica;
IReplicationAgent
IReplicationAgent iRepAgent
iRepAgent == new
new ReplicationAgentClass();
ReplicationAgentClass();

try
try {{
iRepAgent.CreateReplica(rVersion,
iRepAgent.CreateReplica(rVersion, iGDSParent,
iGDSParent, iGDSChild,
iGDSChild, rName,
rName,
iRepDesc, iRepOptions);
iRepDesc, iRepOptions);
}}
catch
catch (Exception
(Exception e)
e) {…}
{…}
}}

See How to create a replica in a connected environment


Example: Create Replica in a Disconnected
Environment

• Steps
n Create the replica to a transport file
– initialize geodataserver, create
replicadescription, set replica options (as
shown in connected)
– Use the GDSExportOptionsClass to define
export options such as output format
– Use the GeoDataServer to create the replica
to an output file
o Transfer the transport file to the target
p Import the transport file on the target to complete replica
creation
Create the replica to a transport file
n Create the replica to a transport file from source
CreateReplicaDisconnected(GDSParent,
CreateReplicaDisconnected(GDSParent, RepDescription,
RepDescription, ReplicaOptions)
ReplicaOptions)
……
public
public void
void CreateReplicaDisconnected(IGeoDataServer
CreateReplicaDisconnected(IGeoDataServer iGDSParent,
iGDSParent,
IGPReplicaDescription iRepDesc, IGPReplicaOptions iReplicaOptions)
IGPReplicaDescription iRepDesc, IGPReplicaOptions iReplicaOptions)
{{
String
String rVersion
rVersion == “MyWork”,
“MyWork”,
rName
rName == “MyReplica;
“MyReplica;
esriGDSTransportType
esriGDSTransportType trType
trType == esriGDSTransportTypeUrl;
esriGDSTransportTypeUrl;
IGDSExportOptions
IGDSExportOptions iGDSEOptions
iGDSEOptions == new
new GDSExportOptions();
GDSExportOptions();
iGDSEOptions.ExportFormat
iGDSEOptions.ExportFormat == esriGDSExportFormat.esriGDSExportFormatXml;
esriGDSExportFormat.esriGDSExportFormatXml;
iGDSEOptions.Compressed
iGDSEOptions.Compressed == true;
true;
iGDSEOptions.BinaryGeometry
iGDSEOptions.BinaryGeometry == false;
false;
try
try {{
IGDSData
IGDSData iGDSData
iGDSData == iGDSParent.CreateReplica(rVersion,
iGDSParent.CreateReplica(rVersion, rName,
rName,
iRepDesc, iReplicaOptions, iGDSEOptions, esriGDSTransportTypeUrl);
iRepDesc, iReplicaOptions, iGDSEOptions, esriGDSTransportTypeUrl);
}}
catch
catch (Exception
(Exception e)
e) {…}
{…}
}}
Transport the file and Import
o File can transported manually or automatically
– Manual example: burn file to CD and send through US Mail
– Automated example: use a data distributed service to FTP files
on a regular basis
p Importing the transport file on the target
– Initialize a GeoDataServer for the target and use ImportData
method
//
// reference
reference the
the file
file to
to import
import with
with the
the GDSData
GDSData object
object
IGDSData
IGDSData iGDSData
iGDSData == new
new GDSDataClass();
GDSDataClass();
iGDSData.TransportType
iGDSData.TransportType == esriGDSTransportType.esriGDSTransportTypeURL;
esriGDSTransportType.esriGDSTransportTypeURL;
iGDSData.Compressed
iGDSData.Compressed == true;
true;
iGDSData.URL
iGDSData.URL == @“D:\filestoimport\myreplica.zip";
@“D:\filestoimport\myreplica.zip";
//
// Import
Import the
the replica
replica workspace
workspace document
document to
to create
create the
the replica
replica
iGDSChild.ImportData(iGDSData,
iGDSChild.ImportData(iGDSData,
esriGDSImportFormat.esriGDSImportFormatXmlWorkspace)
esriGDSImportFormat.esriGDSImportFormatXmlWorkspace)

See How to create a replica in a disconnected environment


Creating Replicas - Best Practices

• Define your replica description for what you want to synchronize


- Replica schema synchronization only supports adding simple
feature classes and tables

• Use replica registration option for large dataset replica creation

• Getting related objects is expensive so use this option only when it


is necessary

• Use GeoDataServer instead of ReplicationAgent when creating


checkout to a new Personal GDB or FileGDB
Creating Replicas - Replica Creation Events
• Developers may wish to extend the core replication behavior

• The replication creation process can be extended by


implementing a Workspace extension that supports
IWorkspaceReplicaEvents

• See About Workspace Extensions


Interface
Interface IWorkspaceReplicaEvents
IWorkspaceReplicaEvents :: IUnknown
IUnknown
{{
HRESLT
HRESLT BeforeCreatingReplicaEvents(BSTR
BeforeCreatingReplicaEvents(BSTR replicaName,
replicaName,
esriReplicaType
esriReplicaType rType,
rType,
IReplicaDescription*
IReplicaDescription* iRDesc,
iRDesc,
IWorkspace*
IWorkspace* childWS);
childWS);

HRESULT
HRESULT AfterCreatingReplicaEvents(BSTR
AfterCreatingReplicaEvents(BSTR replicaName,
replicaName,
esriReplicaType
esriReplicaType rType,
rType,
IReplicaDescription*
IReplicaDescription* iRDesc,
iRDesc,
IWorkspace* iChildWS);
IWorkspace* iChildWS);
};
};
WorkspaceExtension With ReplicaEvents

• WSExtension needs to support IWorkspaceExtensionControl,


IWorkspaceExtension and IWorkspaceReplicaEvents interfaces

• WSExtension needs to be registered as COM object (regasm.exe,


regsvr32.exe)

• WSExtension needs to be registered with the workspace

Interface
public void IWorkspaceReplicaEvents :: IUnknown
RegisterExtension(IWorkspace iWS,
Interface
public voidIWorkspaceReplicaEvents
RegisterExtension(IWorkspace iWS, String
IUnknown String extGUID)
extGUID)
{{{{
HRESLT
HRESLT BeforeCreatingReplicaEvents(BSTR
IWorkspaceExtensionManager iWSMgr replicaName,
iWSMgr == iWS
BeforeCreatingReplicaEvents(BSTR
IWorkspaceExtensionManager iWS as IWorkspaceExtensionManager;
asreplicaName,
IWorkspaceExtensionManager;
UID esriReplicaType
esriReplicaType rType,
UID uid
uid == new
new UID();
UID(); rType,
uid.Value IReplicaDescription
IReplicaDescription rDesc,
uid.Value == extGUID;
extGUID; rDesc,
IWorkspaceExtension IWorkspace*
IWorkspace* childWS);
IWorkspaceExtension iWSExtiWSExt == iWSMgr.FindExtension(uid);
childWS);
iWSMgr.FindExtension(uid);
if
if (iWSExt
(iWSExt == == null)
null) {{
HRESULT
try AfterCreatingReplicaEvents(BSTR }} replicaName,
try {{ iWSMgr.RegisterExtension(uid);
HRESULT AfterCreatingReplicaEvents(BSTR
iWSMgr.RegisterExtension(uid); replicaName,
catch esriReplicaType
esriReplicaType rType,
catch (COMException
(COMException ce)ce) {…}
{…} rType,
}} IReplicaDescription
IReplicaDescription rDesc,
rDesc,
}} IWorkspace*
IWorkspace* childWS);
childWS);
};
Replica Creation Demo

• Build a custom workspace extension to augment replica creation with non-


versioned tables using C#
• 9.3 beta web how to article:
http://edndoc.esri.com/arcobjects/9.3/NET/2e77fc43-39a1-4685-a7f3-
d0122ed7ca10.htm

1. Build workspace extension

DLL

2. Register workspace
extension
3. Create Replica
Before event
Parent Child
After event
Altering Replica Definition
Replica description can be changed after creating a replica

public
public void
void AlterReplica(IWorkspace
AlterReplica(IWorkspace iWS,
iWS, string
string tableName,
tableName, string
string dbase,
dbase,
string owner
string owner
)) {{
IWorkspaceReplicas
IWorkspaceReplicas iWR
iWR == iWS
iWS new
new IWorkspaceReplicas;
IWorkspaceReplicas;
IReplica
IReplica iReplica
iReplica == iWS.get_ReplicaByName(“MyReplica”);
iWS.get_ReplicaByName(“MyReplica”);
IReplicaDescription
IReplicaDescription iRDiRD == iReplica.Description;
iReplica.Description;
int
int index
index == iRD.FindTable(tableName);
iRD.FindTable(tableName);

IReplicaFilterDescriptionEdit
IReplicaFilterDescriptionEdit iFD
iFD == iRD
iRD as
as IReplicaFilterDescriptionEdit;
IReplicaFilterDescriptionEdit;
iFD.put_RowsType(index,
iFD.put_RowsType(index, esriRowsType.esriRowsTypeAll);
esriRowsType.esriRowsTypeAll);

IWorkspaceReplicasAdmin
IWorkspaceReplicasAdmin iRAdmin
iRAdmin == iWR
iWR as
as IWorkspaceReplicasAdmin;
IWorkspaceReplicasAdmin;
try
try {{
iRAdmin.AlterReplica(iReplica);
iRAdmin.AlterReplica(iReplica);
}}
catch
catch (COMException
(COMException ce)
ce)
{…}
{…}
}}
Adding a Dataset to a Replica

• Simple feature classes and tables can be added to a


replica once it has been created
• Data must meet replication requirements
• Feature class or table must be added to both the parent
and the child replicas
• Use the RegisterReplicaDataset method from the
IWorkspaceReplicasAdmin2 interface
– This includes the filter and relationship class criteria
Synchronizing Replicas

• Replica can be synchronized in connected and disconnected


environments

• Synchronize replica changes using ReplicationAgent requires


specifying a sync direction (Child->Parent, Parent->Child or Both)

• Use the GeoDataServer to synchronize replica changes from delta


Updategram (xml, fileGDB, or Personal GDB)

• Explicit versus implicit acknowledgment during replica


synchronization

• Replica synchronization does not allow synchronizing out-of-order


messages (e.g., Sync(Gen1)->Sync(Gen2), Sync(Gen4))
Example: Synchronize Replicas in a Connected
Environment

• Steps
n Initialize a GeoDataServer for the source and target
geodatabases
o Use the ReplicationAgent to Synchronize the replica
//
// Sync
Sync the
the replica
replica
IReplicationAgent
IReplicationAgent iRepAgent
iRepAgent == new
new ReplicationAgentClass();
ReplicationAgentClass();
iRepAgent.SynchronizeReplica(iParentGDS,
iRepAgent.SynchronizeReplica(iParentGDS, /*
/* Parent
Parent geodataserver
geodataserver */
*/
iChildGDS,
iChildGDS, /* child geodataserver
/* child geodataserver */*/
iGPReplicaParent,
iGPReplicaParent, /*
/* Parent
Parent replica
replica */
*/
iGPReplicaChild,
iGPReplicaChild, /*
/* Child
Child replica
replica */
*/
esriRAResolveConflictsInFavorOfReplica1,
esriRAResolveConflictsInFavorOfReplica1, /* /* Reconcile
Reconcile policy
policy */
*/
esriReplicaSynchronizeBoth,
esriReplicaSynchronizeBoth, /*
/* Sync
Sync Direction
Direction */
*/
true);
true); /*
/* true
true == column
column level
level conflicts
conflicts detection
detection */
*/

See How to synchronize a replica in a connected environment


Example: Synchronize Replicas in a
Disconnected Environment

• Steps
n Export replica changes to a transport file
o Transfer the transport file to the target
• Manual example: burn file to CD and send
through US Mail
• Automated example: use a data distributed
service to FTP files on a regular basis
p Import the transport file on the target to complete replica
synchronization
See How to synchronize a replica in a disconnected environment
Synchronizing Replicas (Exporting Changes)
Replica changes can be exported to xml, fileGDB, or personal GDB

public
public void
void ExportReplicaChanges(IGeoDataServer
ExportReplicaChanges(IGeoDataServer iGDS,
iGDS, String
String rName)
rName)
{{
IGDSExportOptions
IGDSExportOptions iExOptions
iExOptions == new
new GDSExportOptions();
GDSExportOptions();
iExOptions.ExportFormat
iExOptions.ExportFormat == esriGDSExportFormat.esriGDSExportFormatXml
esriGDSExportFormat.esriGDSExportFormatXml
iExOptions.Compressed
iExOptions.Compressed == true;
true;
iExOptions.BinaryGeometry
iExOptions.BinaryGeometry == true;
true;
esriGDSTransportType
esriGDSTransportType tType
tType == esriGDSTransportType.esriGDSTransportTypeUrl;
esriGDSTransportType.esriGDSTransportTypeUrl;
esriExportGenerationsOption
esriExportGenerationsOption gOption
gOption ==
esriExportGenerationsOption.esriExportGenerationAll;
esriExportGenerationsOption.esriExportGenerationAll;

IGDSData
IGDSData iGDSData
iGDSData ==
iGDS.ExportReplicaChanges(rName,
iGDS.ExportReplicaChanges(rName, iExOptions,
iExOptions, tType,
tType, gOption,
gOption,
false);
false); /*
/* swtich
swtich role
role to
to be
be aa receiver
receiver */
*/

System.Net.WebClient
System.Net.WebClient wc
wc == new
new System.Net.WebClient();
System.Net.WebClient();
wc.DownLoadFile(iGDSData.URL,
wc.DownLoadFile(iGDSData.URL, @“C:\delta.zip”);
@“C:\delta.zip”);
wc.Dispose();
wc.Dispose();
}}
Synchronizing Replicas (Importing Changes)
Replica changes can be imported from xml, fileGDB, or personal GDB

public
public void
void ImportReplicaChanges(IGeoDataServer
ImportReplicaChanges(IGeoDataServer iGDS,
iGDS, String
String rName)
rName)
{{
String
String fileName
fileName == new
new String(@”C:\delta.zip”);
String(@”C:\delta.zip”);
FileInfo
FileInfo fInfo
fInfo == new
new FileInfo(fileName);
FileInfo(fileName); int
int len
len == fInfo.Length;
fInfo.Length;
byte
byte []
[] bytes
bytes == new
new byte[len];
byte[len];
FileStream
FileStream fsfs == File.Open(fileName,
File.Open(fileName, FileMode.Open,
FileMode.Open, FileAccess.Read);
FileAccess.Read);
BinaryReader
BinaryReader rr == new
new BinaryReader(fs);
BinaryReader(fs);
r.Read(bytes,
r.Read(bytes, 0,
0, len);
len);
r.Close();
r.Close(); fs.Close();
fs.Close();

IGDSData
IGDSData iGDSData
iGDSData == new
new GDSDataClass();
GDSDataClass();
iGDSData.TransportType
iGDSData.TransportType == esriGDSTransportTypeEmbedded;
esriGDSTransportTypeEmbedded;
iGDSData.set_EmbeddedData(ref
iGDSData.set_EmbeddedData(ref bytes);
bytes);
esriReplicaInputSource
esriReplicaInputSource rSrc
rSrc == esriGDSReplicaImportSourceDeltaXmlFile;
esriGDSReplicaImportSourceDeltaXmlFile;
esriReplicaReconcilePolicyType
esriReplicaReconcilePolicyType recPolicy
recPolicy == esriReplicaDetectConflicts;
esriReplicaDetectConflicts;
bool
bool conflicts
conflicts == iGDS.ImportReplicaChanges(rSrc,
iGDS.ImportReplicaChanges(rSrc, recPolicy,
recPolicy,
true,
true, /*
/* column
column conflicts
conflicts detection
detection */
*/
iGDSData);
iGDSData);
}}
Synchronize Replicas – Replica Sync Events

• The replication sync process can be extended by implementing a


workspace extension that supports IWorkspaceSyncReplicaEvents

Interface
Interface IWorkspaceReplicaSyncEvents
IWorkspaceReplicaSyncEvents :: IUnknown
IUnknown
{{
……
HRESLT
HRESLT BeforeSynchronizingDataChanges(IReplica*
BeforeSynchronizingDataChanges(IReplica* iTargetReplica,
iTargetReplica,
IUnknown*
IUnknown* iDeltaDataChanges)
iDeltaDataChanges)

HRESULT
HRESULT AfterSynchronizingDataChanges(IReplica*
AfterSynchronizingDataChanges(IReplica* iTargetReplica,
iTargetReplica,
IUnknown*
IUnknown* iDeltaDataChanges,
iDeltaDataChanges,
ITable*
ITable* iOIDMappingTable,
iOIDMappingTable,
ITable*
ITable* iChangesTable);
iChangesTable);
};
};
Fine Grained API: Inspecting Replica Changes
Developers may need to get the replica changes without exporting them

public
public ArrayList
ArrayList ReadReplicaChanges(IReplica
ReadReplicaChanges(IReplica iReplica,
iReplica, IWorkspaceName
IWorkspaceName iName)
iName)
{{
IReplicaDataChangeInit2
IReplicaDataChangeInit2 iInit
iInit == new
new ReplicationDataChangesClass();
ReplicationDataChangesClass();
esriExportGenerationsOption
esriExportGenerationsOption gOption
gOption ==
esriExportGenerationsOption.esriExportGenerationsNew;
esriExportGenerationsOption.esriExportGenerationsNew;
try
try {{
iInit.Init2(iReplica,
iInit.Init2(iReplica, iName,
iName, gOption);
gOption);
}}
catch
catch (COMException
(COMException e)
e) {…}
{…}

IDataChanges
IDataChanges iRDC
iRDC == iInit
iInit as
as IDataChanges;
IDataChanges;
IEnumModifiedClassInfo
IEnumModifiedClassInfo iMCInfos
iMCInfos == iRDC.GetModifiedClasses();
iRDC.GetModifiedClasses();
ArrayList
ArrayList al
al == new
new ArrayList();
ArrayList();
IModifiedClassInfo
IModifiedClassInfo iMCIiMCI == null
null ;;
while
while ((iMCI
((iMCI == iMCInfos.Next())
iMCInfos.Next()) !=
!= null)
null)
al.Add(mcInfo.Name);
al.Add(mcInfo.Name);
return
return al;
al;
}}
Synchronization Algorithm Internals

• Inserts maybe applied as updates if already exist

• Updates maybe applied as inserts if not already exist

• Synchronization preserves only GlobalIDs (not OIDs)

• OIDs Mapping table is created for new rows

• To preserve relationships where the origin key is an


ObjectID, foreign keys are swizzled for newly allocated
ObjectIDs
Synchronization Algorithm Internals

• Except for creating topology dirty areas and rebuilding GN


connectivity, no behaviors are executed when synchronizing
changes

• Validating topology might be needed after replica synchronization

• Sync replica rebuilds geometric network connectivity only for the


changes and the area affected by the changes

• Related objects are synchronized based on the relationship


directions specified at the replica creation

• Conflict version is created when Rec/Post the changes with the


replica version fails

• Overlapping replica generations is accepted (Gen1, Gen1->3)


Synchronize Replica - Best Practice

• Use acknowledgment after disconnected synchronization if


possible

• Export only new changes if you know that the prior sent changes
were received by the target replica

• Synchronize changes as often as possible

• Use delta FileGDB as an updategram unless you need to work with


XML

• Use IWorkspace3::get_RecommendedSyncOrder to find out which


replicas need to be synchronized before compressing the
geodatabase
Replica Sync Order
Developers may need to sync replicas before compressing the geodatabase

public
public ArrayList
ArrayList GetRecommendedReplicasSyncOrder(IWorkspace
GetRecommendedReplicasSyncOrder(IWorkspace iWS)
iWS)
{{
IVersionedWorkspace3
IVersionedWorkspace3 iVWS
iVWS == iWS
iWS as
as IVersionedWorkspace3;
IVersionedWorkspace3;
IEnumBSTR
IEnumBSTR iRepNames
iRepNames == null;
null;
try
try {{
iRepNames
iRepNames == iVWS.RecommendedSyncOrder;
iVWS.RecommendedSyncOrder;
catch
catch {{
return
return null;
null;
}}
IWorkspaceReplicas
IWorkspaceReplicas iWSReplicas
iWSReplicas == iWS
iWS as
as IWorkspaceReplicas;
IWorkspaceReplicas;
ArrayList
ArrayList al
al == new
new ArrayList();
ArrayList();
string
string rName;
rName;
while
while ((rName
((rName == iRepNames.Next())
iRepNames.Next()) !=
!= null)
null) {{
IReplica
IReplica iReplica
iReplica == iWSReplicas.get_ReplicaByName(rName);
iWSReplicas.get_ReplicaByName(rName);
al.Add(iReplica);
al.Add(iReplica);
}}
return
return al;
al;
}}
Fine Grained API: Version Differences
Developers may need to import version differences to the replica version
public
public void
void ExportVersionChanges(IWorkspaceName
ExportVersionChanges(IWorkspaceName iSRC,
iSRC, IWorkspaceName
IWorkspaceName iTrg)
iTrg)
{{
IVersionDataChangesInit
IVersionDataChangesInit iVInit
iVInit == new
new VersionDataChangesClass();
VersionDataChangesClass();
try
try {{
iVInit.Init(iSRC,
iVInit.Init(iSRC, iTrg);
iTrg);
}}
catch
catch (COMException
(COMException e)
e) {…}
{…}
IExportDataChanges
IExportDataChanges iEDC
iEDC == new
new DataChangesExporter();
DataChangesExporter();
esriExportDataChangesOption
esriExportDataChangesOption exOption
exOption ==
esriExportDataChangesOption.esriExportToXML;
esriExportDataChangesOption.esriExportToXML;
try
try {{
iEDC.ExportChanges(@”C:\VersionDiff.xml”,
iEDC.ExportChanges(@”C:\VersionDiff.xml”,
exOption,
exOption,
iVInit
iVInit as
as IDataChanges,
IDataChanges,
false);
false); /*
/* overwrite
overwrite if
if exists
exists */
*/
}}
catch
catch (COMException
(COMException ce)
ce)
{{ …
… }}
}}
Fine Grained API: Tables Differences
public
public void
void ExportTableChanges(ITable
ExportTableChanges(ITable iInserts,
iInserts, ITable
ITable iUpdates,
iUpdates, IStringArray
IStringArray
iDeletes)
iDeletes)
{{
ITablesDataChanges
ITablesDataChanges iTDCs
iTDCs == new
new TablesDataChangesClass();
TablesDataChangesClass();
try
try {{
ITableDataChange
ITableDataChange iTDC
iTDC == new
new TableDataChange();
TableDataChange();
iTDC.Init(“Parcel”,
iTDC.Init(“Parcel”, iInserts,
iInserts, iUpdates,
iUpdates, null);
null);
iTDC.SetDeletedIDs(null,
iTDC.SetDeletedIDs(null, iDeletes);
iDeletes);
iTDCs.Add(ipTDC);
iTDCs.Add(ipTDC);
}}
catch
catch (COMException
(COMException e)
e) {…}
{…}
IExportDataChanges
IExportDataChanges iEDC
iEDC == new
new DataChangesExporter();
DataChangesExporter();
try
try {{
iEDC.ExportChanges(@”C:\TableDiffs.xml”,
iEDC.ExportChanges(@”C:\TableDiffs.xml”,
esriExportDataChangesOption.esriExportToXML,
esriExportDataChangesOption.esriExportToXML,
iTDCs
iTDCs as
as IDataChanges,
IDataChanges,
false);
false); /*
/* overwrite
overwrite if
if exists
exists */
*/
}}
catch
catch (COMException
(COMException ce)
ce)
{{ …
… }}
}}
Fine Grained API: Importing Differences
Developers may need to import version/Tables differences to the replica
public
public void
void ImportChanges(IWorkspaceName
ImportChanges(IWorkspaceName iReplicaWorkspace)
iReplicaWorkspace)
{{
IDeltaDataChangesInit
IDeltaDataChangesInit iInit
iInit == new
new DeltaDataChangesClass();
DeltaDataChangesClass();
try
try {{
iInit.Init(@”C:\diffs.xml”,
iInit.Init(@”C:\diffs.xml”, esriExportToXML);
esriExportToXML);
}}
catch
catch (COMException
(COMException e)
e) {…}
{…}
IImportDataChanges2
IImportDataChanges2 iImportDC
iImportDC == new
new DataChangesImporterClass();
DataChangesImporterClass();
try
try {{
bool
bool conflicts
conflicts == iImportDC.ImportDataChanges2(
iImportDC.ImportDataChanges2(
iRepWorkspace,
iRepWorkspace,
iInit
iInit as
as IDeltaDataChanges,
IDeltaDataChanges,
true,
true, /*/* reconcile
reconcile with
with the
the parent
parent version
version */
*/
esriReplicaReconcilePolicyType.esriReplicaDetectConflicts,
esriReplicaReconcilePolicyType.esriReplicaDetectConflicts,
true,
true, /*
/* column
column level
level conflicts
conflicts detection
detection */
*/
true);
true); /*
/* create
create oid
oid mapping
mapping table
table */
*/
}}
catch
catch (COMException
(COMException ce)
ce) {…}
{…}
}}
Enhancements – User Defined GlobalIDs

• Allows users who already manage their own unique


identifiers to start using geodatabase globalid columns
• New interface (IClassSchemaEX) allows you to control
the globalid values
– Add user defined GUID values to a column of type GUID
– Use IClassSchemaEX to convert the GUID column a to GlobalID
column
– IClassSchemaEX can also be used to change the type from
GlobalID to GUID such that more changes can be made
• Not supported in a versioned environment
Replication Interoperability with non-
geodatabase formats
• Replication where the parent is a geodatabase and the
child is a non-geodatabase format

• Use the data interoperability extension to build 1 way


replication and check-out replication workflows

• To check in it is required to generate an ESRI XML data


change file programmatically
– Use ESRI’s published XML schema of the geodatabase
1 way replication workflow

• Create Replica
External System
Create 1 way convert data
Parent replica Child (Interop ext)
Geodatabase Geodatabase

• Synchronize Replica
External System
Synchronize convert data
Changes (Interop ext)
Parent Child
Geodatabase Geodatabase
Check-out replication workflow

V V
Enterprise
Geodatabase

XML Workspace doc Check Out Check In

Data Change File


OR XML
Geodatabase

Convert Data External System Generate ESRI XML


(Interop extension) data change file
programmatically
Replication Interoperability with External Systems

• Simple versus full geodatabase replication model

• Check in supports both simple and full geodatabase model

• Check in from external system requires a knowledge of the


checkout guid

• Check in synchronization order


ESRI XML Data Change File
<esri:UpdateGram xmlns:esri=http://www.esri.com/schemas/ArcGIS/9.2… >
<GeodatabaseRelease>…</GeodatabaseRelease>
<GUID>D6A7E5C3-9EF0-45DE-B412-55502DAEEEC4</GUID>
<ParentID>70</ParentID>
<ParentConnectionInfo>…</ParentConnectionInfo>
<ModelType>esriModelTypeFullGeodatabase</ModelType>
<UpdateGramDefinition>
<ChangedDatasetDefinition>
<DatasetName>states</DatasetName>
<DatasetType>esriDTFeatureClass</DatasetType>
<ParentDB />
<ParentOwner>BOB</ParentOwner>
</ChangedDatasetDefinition>
</UpdateGramDefinition>
<UpdateGramTopologyDefinition />
<UpdateGramData>…</UpdateGramData>
</esri:Updategram>
ESRI Developer Summit 2008 56
In Conclusion…

• Other recommended sessions and meetings


To do

• All sessions are recorded and will be available on EDN


– Slides and code will also be available

• Please fill out session surveys!

• Still have questions?


1. Tech talk, Demo Theatres, Meet the Team
2. “Ask a Developer” link on web page
• www.esri.com/devsummit/techquestions
ESRI Developer Summit 2008 57