Problem changing paths of featureclasses in feature dataset using arcpy

3315
5
10-12-2010 02:27 PM
MichaelBishopp
Occasional Contributor
I am trying to change a path from Oracle SDE to SQL Server SDE.  The feature classes that I am trying to repath are found within featuredatasets.  The basic code that I am using is:


                          
 mxd = arcpy.mapping.MapDocument(fullpath)
                        
                            DFList = arcpy.mapping.ListDataFrames(mxd)
                    
                            for df in DFList:
                                lyrList = arcpy.mapping.ListLayers(mxd, "", df)
                    
                                for lyr in lyrList:
                                    if lyr.supports("DATASOURCE"):
                                        
                                        sourcePath = os.path.dirname(lyr.dataSource)
                                        
                                        if lyr.dataSource.count(".sde") > 0:

                                           mxd.findAndReplaceWorkspacePaths(sourcePath,
                                           r"Database Connections\Test_CartaTest_GISUSER.sde\CartaTest.TRANS.BikeFeatures") #change to Carta instead of CartaTest when done
                    


The original data is found in "Database Connections\GIS_USER2PGIS.sde\TRANS.BikeFeatures.
The new data (as shown above) needs to be repathed to: "Database Connections\Test_CartaTest_GISUSER.sde\CartaTest.TRANS.BikeFeatures

Can anyone tell me if this is the correct approach?  Would it be better to do something like this:

lyr.replaceDataSource(r"Database Connections\Test_CartaTest_GISUSER.sde\CartaTest.TRANS.BikeFeatures", "SDE_WORKSPACE", "BikeFeatures") <--BTW, this exact syntax doesn't work.
0 Kudos
5 Replies
JeffMoulds
Esri Contributor
If you need to drill down to the individual layers in your mxd, then layer.replaceDataSource or layer.findAndReplaceWorkspacePath would be the way to go. For example, if only some of you sde layers needed to be changed, or the feature class or feature dataset names dont match, etc. The help states:

- The findAndReplaceWorkspacePath method on the Layer object is intended to perform a find and replace of the workspace path for a single layer in a map document or a layer file.

- The replaceDataSource method on the Layer object is similar to the findAndReplaceWorkspacePath method, but in addition to changing a workspace, the dataset can be changed. This is the only method that enables you to replace a layer's dataset within a workspace. This is especially useful when the name of a dataset is different in the new workspace.

However, if you are migrating all Oracle layers in your map(s) to SQL Server, I would first try something easy like this:

import arcpy
mxd = arcpy.mapping.MapDocument(r"C:\temp\sde_test.mxd")
mxd.findAndReplaceWorkspacePaths(r"Database Connections\Connection to Oracle.sde", 
                                 r"Database Connections\Connection to SQL Server.sde")
mxd.saveACopy(r"C:\temp\migrate_server.mxd")
del mxd
print "done"


Tip: The SDE connection file information used in the script must be identical to the SDE connection used to add data to a map document or layer file. The dataSource property on the Layer and TableView objects provides a way to determine the path that is being used in the map document or layer file. Use this value to help determine which SDE connection file path should be used.

Tip: check out this help topic: http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#/Updating_and_fixing_data_sources_with_...
0 Kudos
MichaelBishopp
Occasional Contributor
Jeff,

I'm pretty sure I understand all that you are saying--and I know that i have implemented what you are saying into my existing script.  My BIG question is how do I repath a featureclass that is in a feature dataset from one database to the other.  I have tried all the methods you suggest to no avail.  I just want to know if I am missing something OR if there is some other solution that is not apparent.

Thanks,

Michael
0 Kudos
MichaelBishopp
Occasional Contributor
I got this response from Jeff Barrette of ESRI - Olympia:

Hi Michael,

The examples that I�??ve documented for changing SDE workspaces is to simply use the path to the .sde file.  In your example,

Find_workspace_path = r�?�Database Connections\GIS_USER2PGIS.sde�?�
Replace_workspace_path = r"Database Connections\Test_CartaTest_GISUSER.sde�?�

It should not matter if the feature class is in a feature dataset.  If the feature class name has changed, then you must use lyr.replaceDataSource.  You are using sourcePath=lyr.dataSource.  No, it should be similar to lyr.workspace [its actually lyr.workspacePath].  You are replacing a workspace path, not a datasource path.

Please let me know if this works, this is how it is documented.

Jeff

************************
All of Jeff's advise worked.  Thanks Jeff!
0 Kudos
YoshihiroWatanabe
New Contributor

I tried to change a layer's dataSource in a gdb, and to different feature class dataset in another gdb.

It took long time that I grasped replaceDataSource needs only gdb path.

Any dataset name is not necessary.

(ex)

    if you want to change " fc1 in a.gdb\datasetA " to " fc2 in b.gdb\datasetB "

    C:\a.gdb\datasetA\fc1 -> C:\b.gdb\datasetB\fc2

    you need to prepare 3 informations : 

      1. where to change : "C:\b.gdb"    dataset name is not necessary !!

      2. type of workspace: "FILEGDB_WORKSPACE"

      3. name of datasource : "datasetB"  if this is RASTER, it needs an extension of the file(RASTER_WORKSPACE), but is SHAPEFILE(SHAPEFILE_WORKSPACE), it dont need an extention.

 

    then, they apply to the function:

      lyr.reaplceDataSource(  1 , 2 , 3 )

It may not be an answer you needs.

I hope that it will be helpful for you.

references:

  1 [1] arcpy - Using Feature Dataset with ReplaceDataSource gives ValueError: Layer: Unexpected error? - Ge... 

  3 [2] python - Arcpy's replaceDataSource Error - Geographic Information Systems Stack Exchange 

0 Kudos
JeffMoulds
Esri Contributor
I just tried going from Oracle to SQL Server.

If the feature class name, feature dataset name and username are all the same between the two servers, you can use the following code, which doesnt drill down to all the dataframes and layers. For example, my datasources look like this:

Oracle: Database Connections\Connection to tempest map.sde\MAP.JeffM\MAP.jcities
SQL Server: Database Connections\Connection to betty4.sde\vtest.MAP.JeffM\vtest.MAP.jcities

import arcpy
from time import gmtime, strftime

Oracle = r"Database Connections\Connection to tempest map.sde"
SQLServer = r"Database Connections\Connection to betty4.sde"

mxd = arcpy.mapping.MapDocument(r"C:\temp\analysts\forum\sde\Oracle_map.mxd")

# examine the input data source - just looking at the first layer
lyr = arcpy.mapping.ListLayers(mxd)[0]
print "Input data source:", lyr.dataSource

mxd.findAndReplaceWorkspacePaths(Oracle, SQLServer)
mxd.saveACopy(r"C:\temp\analysts\forum\sde\SQLServer_map.mxd")
del mxd, lyr

#examine the output data source - just looking at the first layer
mxd2 = arcpy.mapping.MapDocument(r"C:\temp\analysts\forum\sde\SQLServer_map.mxd")
lyr2 = arcpy.mapping.ListLayers(mxd2)[0]
print "Output data source:", lyr2.dataSource
del mxd2, lyr2

print "Completed at", strftime("%Y-%m-%d %H:%M:%S", gmtime())
print "========================================"


If you need to drill down to the layer, you can use something like the code below. In my case, the feature data set names and the feature class names are the same, but the username is different. My paths looked like this:

Oracle: Database Connections\Connection to bulgaria catalog.sde\CATALOG.JeffM\CATALOG.jcities
SQL Server: Database Connections\Connection to betty4.sde\vtest.MAP.JeffM\vtest.MAP.jcities

import arcpy
from time import gmtime, strftime

SQLServer = r"Database Connections\Connection to betty4.sde"
mxd = arcpy.mapping.MapDocument(r"C:\temp\analysts\forum\sde\Oracle_cat.mxd")
lyrs = arcpy.mapping.ListLayers(mxd)
for lyr in lyrs:
    #examine the input data sources
    print "Input data source:", lyr.dataSource
    lyr.replaceDataSource(SQLServer, "SDE_WORKSPACE", lyr.datasetName, True)
mxd.saveACopy(r"C:\temp\analysts\forum\sde\SQLServer_map.mxd")
del mxd, lyr

#examine the output data source - just looking at the first layer
mxd2 = arcpy.mapping.MapDocument(r"C:\temp\analysts\forum\sde\SQLServer_map.mxd")
lyr2 = arcpy.mapping.ListLayers(mxd2)[0]
print "Output data source:", lyr2.dataSource
del mxd2, lyr2

print "Completed at", strftime("%Y-%m-%d %H:%M:%S", gmtime())
print "========================================"
0 Kudos