2

I am using updateConnectionProperties() method to change data sources for layer files. The layer is "C:/gis/layer.lyrx". The old path is "C:/gis/oldGDB.gdb/oldDS/FC". The new path is "C:/gis/newGDB.gdb/FC". As you can see, the new data source is not in a feature dataset like the old one. First I tried:

lyr = arcpy.mp.LayerFile('C:/gis/layer.lyrx')
lyr.updateConnectionProperties('C:/gis/oldGDB.gdb', 'C:/gis/newGDB.gdb')
lyr.saveACopy('C:/gis/newLayer.lyrx')

When I check the property of newLayer.lyrx, its data source is unchanged - still the FC in oldDS in oldGDB.gdb. Then I tried:

lyr = arcpy.mp.LayerFile('C:/gis/layer.lyrx')
lyr.updateConnectionProperties('', 'C:/gis/newGDB.gdb')
lyr.saveACopy('C:/gis/newLayer.lyrx')

The data source did change this time, but it assumed that the new source is still in a dataset, and thus it could not find the new source. Lastly, I tried:

lyr = arcpy.mp.LayerFile('C:/gis/layer.lyrx')
lyr.updateConnectionProperties('', {'connection_info': 
   {'database': 'C:/gis/newGDB.gdb'}, 
    'dataset': '', 
    'workspace_factory': 'File Geodatabase'})
lyr.saveACopy('C:/gis/newLayer.lyrx')

Again, the data source did not change. How can I make it work?

3 Answers 3

1

Late reply but maybe it will help people finding this post and having the same problem. The .updateConnectionProperties method did nothing when used on layer in my case, so a defined a function using the Python CIM access to change the data source from a featureclass file in a GDB.

In this function, no need to specify the feature dataset name, arcpy will handle this automatically (because you can't have feactureclass with the same name in a gdb). This work with GDB that don't have feature dataset AND with GDB that have feature class datasets.

def update_layer_source(layer, new_gdb_path, new_feature_name, new_feature_dataset=None):
    """Use Python CIM access to modify a layer data source
    https://pro.arcgis.com/en/pro-app/latest/arcpy/mapping/python-cim-access.htm
    """
    if not isinstance(layer, arcpy._mp.Layer):
        raise TypeError(f"layer arg must be a arcpy.mp.Layer object")
    lyrCIM = layer.getDefinition('V3') 
    data_source = lyrCIM.featureTable.dataConnection
    
    data_source.dataset = new_feature_name
    data_source.workspaceConnectionString = f'DATABASE={new_gdb_path}'
    if new_feature_dataset !=None: 
        data_source.featureDataset = new_feature_dataset
    
    layer.setDefinition(lyrCIM)
    
    return None

How to use :

# Import your lyr file or select it in the map
_map = arcpy.mp.ArcGISProject("CURRENT").listMaps('your_map_name')[0]
lyr = _map.listLayers('your_lyr_name')[0]

# Change Data Source of your layer
update_layer_source(lyr, 'your_new_gdb_path', 'your_new_feature_name')
2
  • 1
    Very nice workaround. However your function didn't work for me when I was changing feature class data source between different datasets in different gdbs (i.e. updating data source from a.gdb/a1/fc to b.gdb/b1/fc). To make it working in my case I modified function signature to 'def update_layer_source(layer, new_gdb_path, new_feature_name, new_feature_dataset=None:' and then in function body after defining data_source I've added 'if new_feature_dataset !=None: data_source.featureDataset = new_feature_dataset'
    – Szym
    Jun 20, 2023 at 14:24
  • thx, I added your suggestion to my answer
    – Paulloed
    Jul 17, 2023 at 13:45
0

Try this:

lyr = arcpy.mp.LayerFile('C:/gis/layer.lyrx')
current_conn = lyr.connectionProperties
new_conn = {'dataset':'your_new_file', 
            'workspace_factory': 'File Geodatabase',
            'connection_info':{'database': 'your_gdb_path'})
lyr.updateConnectionProperties(current_conn, new_conn)
lyr.saveACopy('C:/gis/newLayer.lyrx')
1
  • It says 'LayerFile' object has no attribute 'connectionProperties'. I am having trouble understanding the difference between Layer class and LayerFile class. My layer file has only one layer. Jun 29, 2021 at 13:43
0

It may be tripping up on the forward slashes, see if this works:

lyr = arcpy.mp.LayerFile(r'C:\gis\layer.lyrx')

for layer in lyr.listLayers():
    layer.updateConnectionProperties(r'C:\old.gdb', r'C:\data\newGDB.gdb')

lyr.saveACopy(r'C:\gis\newLayer.lyrx')

(I suspect lyr.updateConnectionProperties(r'C:\old.gdb', r'C:\data\newGDB.gdb') would do the trick, too).

A layer file can, theoretically, contain multiple layers at its top level so think of it as a container that has-many layers, not a layer itself.

3
  • I tried updateConnectionProperties on both the layer file and the layer with r'C:\...' but neither worked. The data source was not updated at all. The only way that I could actually update the data source was to use empty string as the first parameter in updateConnectionProperties(). I also tried layer.updateConnectionProperties(layer.connectionProperties, r'C:\gis\newGDB.gdb') in the for loop and it still didn't update anything. Jun 29, 2021 at 17:21
  • It seems to me that updateConnectionProperties only works if: 1) both the old and the new data sources are not in datasets, or 2) both the old and the new data sources are in datasets with the same name. Jun 29, 2021 at 18:33
  • As Boyang noted the issue is with datasets and not with forward slashes
    – Szym
    Jun 20, 2023 at 14:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.