更新和修复数据源

在许多情况下,您都可能需要修复数据源或重定向数据源至其他位置。 ArcGIS Pro 中的目录视图具有更新数据源的功能。 然而,在每个相关地图或工程中进行手动更改将会异常麻烦。 arcpy.mp 脚本环境提供了多种方法使得您无需打开工程即可自动进行更改。

以下成员用于更改数据源工作流:

使用 updateConnectionProperties 函数

updateConnectionProperties 函数需要的两个参数如下:

  • current_connection_info - 用于表示工作空间路径或 Python 字典(包含要更新的源的连接属性)的字符串。
  • new_connection_info - 用于表示工作空间路径或 Python 字典(包含连接属性与新源信息)的字符串。

updateConnectionProperties 函数可以被视为是一个用 current_connection_info 参数替换 new_connection_info 参数的查找与替换函数。 这些参数既可以是到工作空间、部分字符串、包含连接属性的字典、定义特定键的部分字典的完整路径,也可以是到数据库连接 (.sde) 文件的路径。 如果空字符串或 None 用于 current_connection_info,则所有连接属性将替换为 new_workspace_info,具体取决于 validate 参数值。

提示:

不要将地理数据库要素数据集的名称包含在 current_connection_infonew_connection_info 参数中。 要素数据集是工作空间的一部分。

auto_update_joins_and_relates 参数允许您控制是否应更新连接、关联或与图层或表相关的事件。 将默认值设为 True。 有时,尤其是在更新工程级别的所有数据源时,您不希望这些相关的数据源更新。 如果是这种情况,请将此参数设置为 False

在默认情况下,updateConnectionProperties 方法仅在 new_connection_info 是有效数据源的情况下更新数据源。 如果将 validate 参数设置为 False,则将数据源设置到该位置,而不考虑其现有位置。 这对尚未创建数据时需要更新数据源的情况十分有用。 在上述情况下,数据在关联的地图中将显示为已损坏。

updateConnectionProperties 函数中将 current_connection_info 参数替换为 new_connection_info 参数时,如果未找到匹配项,您的脚本可能会运行完成,但不会更新任何内容。

要将图层的数据集更改为具有其他名称的要素类,请参阅下面的“更改图层数据集”一节。

常用的 updateConnectionProperties 示例

  1. 以下脚本将更改工程中所有图层和表的文件地理数据库数据源的完整路径。 在本示例中,对文件夹进行了重命名,并将所有矢量数据移动到了这一新位置:

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    aprx.updateConnectionProperties(r'C:\Projects\YosemiteNP\Historic_Data\Yosemite.gdb',
                                    r'C:\Projects\YosemiteNP\New_Data\Yosemite.gdb')
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  2. 以下示例与上述示例非常相似,但该示例将使用部分路径字符串更新数据所在的文件夹。 在此示例中,工作空间路径中所有出现的 Historic_Data 将替换为 New_Data。 请确保使用部分字符串时,不会在路径中多次发生。 您可能不会获得期望的结果。 或者,您可以使用完整路径字符串而不是部分路径字符串。

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    aprx.updateConnectionProperties(current_connection_info='Historic_Data',
                                    new_connection_info='New_Data')
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  3. 以下示例使用地图中所有图层和表的部分路径将个人地理数据库连接替换为文件地理数据库连接:

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    m = aprx.listMaps("Yose*")[0]
    m.updateConnectionProperties(current_connection_info='Background.mdb',
                                 new_connection_info='Background_fGDB.gdb')
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  4. 以下示例参考地图中的图层,并使用连接属性更新尚未更新新数据源的图层文件中相同图层的连接属性。

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    m = aprx.listMaps('Yose*')[0]
    lyr = m.listLayers('Ranger Stations')[0]
    lyrFile = arcpy.mp.LayerFile(r'C:\Projects\YosemiteNP\LYRXs\Yosemite\OperationalLayers.lyrx')
    
    for l in lyrFile.listLayers():
      if l.name == 'Ranger Stations':
        l.updateConnectionProperties(l.connectionProperties, lyr.connectionProperties)
    
    lyrFile.save()
  5. 在此示例中,要素类移至新的文件地理数据库。 脚本会在应用该要素类的工程中搜索所有已损坏图层。 然后将图层的数据源更新为新的文件地理数据库。

    import arcpy, os
    
    featureClass = 'Boundary'
    oldFileGDB = r'C:\Projects\YosemiteNP\Yosemite.gdb'
    newFileGDB = r'C:\Projects\YosemiteNP\YosemiteNew.gdb'
    
    # Reference project
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    
    # Search for specific broken layers
    for m in aprx.listMaps():
        for lyr in m.listLayers():
            if lyr.isBroken:
                if lyr.supports("DATASOURCE"):
                    if lyr.dataSource == os.path.join(oldFileGDB, featureClass):
                        lyr.updateConnectionProperties(oldFileGDB, newFileGDB)
    
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  6. 以下示例通过将 current_connection_info 指定为 None,将所有数据源定向到单一文件地理数据库。 这适用于多个数据源已合并为单一工作空间的情况。

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    aprx.updateConnectionProperties(None, r'C:\Projects\YosemiteNP\New_Data\Yosemite.gdb')
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  7. 在此示例中,需要更新图层的 URL。 脚本将搜索工程中所有引用旧 URL 的图层。 然后,它会将图层的数据源更新为新 URL。

    import arcpy
    
    featureClass = 'Boundary'
    oldURL = 'https://services2.arcgis.com/k4wsDILUIGeQ5HvW/arcgis/rest/services/USAFederalLands/FeatureServer'
    newURL = 'https://services2.arcgis.com/k4wsDILUIGeQ5HvW/arcgis/rest/services/USAFederalLandsUpdated/FeatureServer'
    
    # Reference project
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    
    # Search all layers for the old URL
    for m in aprx.listMaps():
        for lyr in m.listLayers():
            if lyr.supports("DATASOURCE"):
                if oldURL in lyr.dataSource:
                    lyr.updateConnectionProperties(oldURL, newURL)
    
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")

例如,更新企业级地理数据库图层的数据源

  1. 以下示例将文件地理数据库连接替换为工程中所有图层和表的企业级地理数据库连接 (.sde) 文件的路径。

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    aprx.updateConnectionProperties(r'C:\Projects\YosemiteNP\Vector_Data\Yosemite.gdb',
                                    r'C:\Projects\YosemiteNP\DBConnections\Server.sde')
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  2. 以下示例将 current_connection_info 参数中的企业级地理数据库连接文件的连接属性替换为 new_connection_info 参数中的企业级地理数据库连接文件。

    注:

    current_connection_info 参数中指定的企业级地理数据库连接文件无需是用于创建图层的当前连接文件。 更确切地说,连接文件包含的连接属性将用于 updateConnectionProperties 查找和替换功能。

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    aprx.updateConnectionProperties(r'C:\Projects\YosemiteNP\DBConnections\TestGDB.sde',
                                    r'C:\Projects\YosemiteNP\DBConnections\ProductionGDB.sde')
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  3. 以下示例将企业级地理数据库连接文件替换为工程中所有图层和表的文件地理数据库的路径。

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    aprx.updateConnectionProperties(r'C:\Projects\YosemiteNP\DBConnections\Server.sde',
                                    r'C:\Projects\YosemiteNP\Local_Data\YosemiteLocal.gdb')
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  4. 以下示例通过将 current_connection_info 指定为 None,将所有数据源定向到单一企业级地理数据库。 这适用于工程中企业级地理数据库图层的凭据未知或不可用的情况。

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    aprx.updateConnectionProperties(None, r'C:\Projects\YosemiteNP\DBConnections\Server.sde')
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")

使用 connectionProperties 字典

用于更新数据源的 connectionProperties 需要使用连接属性字典。 返回的字典取决于其是基于文件的工作空间还是数据库连接,或者取决于图层或表是否具有相关连接或关联。 由于存在这种变异性,因此有必要了解连接属性的不同类型以及通过导航字典做出相应更改的方法。 例如,具有连接的图层返回的结果与没有连接的同一图层返回的结果不同。 更新连接属性字典的方法是从图层或表中进行参考并检索字典,对其做出必要的更改,然后将修改后的字典重置回您想要使用 updateConnectionProperties 方法更新的图层或表。

显示字典结构的一个不错方法是使用 Python pprint 函数。

import arcpy, pprint
p = arcpy.mp.ArcGISProject('current')
m = p.listMaps()[0]
l = m.listLayers()[0]
pprint.pprint(l.connectionProperties)

例如,不具有连接和关联的基于文件的数据源将如下所示:

{'connection_info': {'database': 'C:\\Projects\\YosemiteNP\\Data\\Yosemite.gdb'}, 
 'dataset': 'RangerStations', 
 'workspace_factory': 'File Geodatabase'}

上述示例是最基本的结构。 返回含三个键的字典。 connection_info 键值是包含 database 路径的另一个字典。

下面是使用 connectionProperties 字典的几个示例:

  1. 以下示例将数据源的数据集名称从 RangerStations 更新为 RangerStationsNew。 它还将地理数据库从 Yosemite.gdb 更新为 YosemiteNew.gdb

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    lyr = aprx.listMaps("Main*")[0].listLayers("Ranger Stations")[0]
    find_dict = {'connection_info': {'database': 'C:\\Projects\\YosemiteNP\\Data\\Yosemite.gdb'}, 
                 'dataset': 'RangerStations', 
                 'workspace_factory': 'File Geodatabase'}
    replace_dict = {'connection_info': {'database': 'C:\\Projects\\YosemiteNP\\Data\\YosemiteNew.gdb'}, 
                    'dataset': 'RangerStationsNew', 
                    'workspace_factory': 'File Geodatabase'}
    lyr.updateConnectionProperties(find_dict, replace_dict)
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  2. 上面的脚本也可以重新编写为以下内容:

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    lyr = aprx.listMaps("Main*")[0].listLayers("Ranger Stations")[0]
    cp = lyr.connectionProperties
    cp['connection_info']['database'] = 'C:\\Projects\\YosemiteNP\\Data\\YosemiteNew.gdb'
    cp['dataset'] = 'RangerStationsNew'
    lyr.updateConnectionProperties(lyr.connectionProperties, cp)
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  3. connectionProperties 字典还可以用于更新基于文件的数据源,例如 shapefile、栅格文件等。 以下示例将图层的数据源更改为指向其他文件夹中的新 shapefile。

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    lyr = aprx.listMaps('Main*').listLayers('RoadsShp')[0]
    cp = lyr.connectionProperties
    cp['connection_info']['database'] = 'C:\\Projects\\YosemiteNP\\Data_New'
    cp['dataset'] = 'NewRoads.shp'
    lyr.updateConnectionProperties(lyr.connectionProperties, cp)
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")

使用含企业级地理数据库数据的 connectionProperties 字典

以下是图层的企业级地理数据库数据源 connectionProperties 字典的示例:

{'connection_info': {'authentication_mode': 'OSA',                     
                     'database': 'TestDB',                     
                     'db_connection_properties': 'TestServer',                     
                     'dbclient': 'sqlserver',                     
                     'instance': 'sde:sqlserver:TestServer',                     
                     'password': '*********',                     
                     'server': 'TestServer',                     
                     'user': 'User',                     
                     'version': 'sde.DEFAULT'}, 
'dataset': 'TestDB.USER.RangerStations', 
'workspace_factory': 'SDE'}

已返回三个相同的键作为文件地理数据库图层,但此次 connection_info 值是具有更大数据库连接属性集的字典。 这些属性中的任何一个都可以修改。

以下示例将更改工程中所有图层的企业级地理数据库实例和服务器。 在此示例中,企业级地理数据库使用操作系统身份验证,并且数据库名称相同。 如果用户名和密码相同,则可以在不知道工程中图层凭据的情况下更改实例和服务器,而无需创建新的企业级地理数据库连接文件。

import arcpy
aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
find_dict = {'connection_info': {'db_connection_properties': 'TestServer',
                                 'instance': 'sde:sqlserver:TestServer',
                                 'server': 'TestServer'}}
replace_dict = {'connection_info': {'db_connection_properties': 'ProdServer',
                                    'instance': 'sde:sqlserver:ProdServer',
                                    'server': 'ProdServer'}}
aprx.updateConnectionProperties(find_dict, replace_dict)
aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")

使用包含连接的 connectionProperties 字典

connectionProperties 字典还将显示该图层上存在的所有连接的属性。 这些属性中的任何一个都可以修改。

下面的示例显示了具有一个连接的基于文件的数据源 connectionProperties 字典:

{'cardinality': 'one_to_many',
 'destination': {'connection_info': {'database': 'C:\\Projects\\FGDB.gdb'},
                 'dataset': 'tabular_eco',
                 'workspace_factory': 'File Geodatabase'},
 'foreign_key': 'ECO_CODE',
 'join_forward': False,
 'join_type': 'left_outer_join',
 'primary_key': 'CODE',
 'source': {'connection_info': {'database': 'C:\\Projects\\FGDB.gdb'},
            'dataset': 'mex_eco',
            'workspace_factory': 'File Geodatabase'}}

示例显示了具有两个连接的基于文件的数据源 connectionProperties 字典:

{'cardinality': 'one_to_many', 
 'destination': {'connection_info': {'database': 'C:\\Projects\\YosemiteNP\\Data\\BackgroundData.gdb'},                 
                 'dataset': 'census2000',                 
                 'workspace_factory': 'File Geodatabase'}, 
 'foreign_key': 'State_Polygons.State_Name', 
 'join_forward': False, 
 'join_type': 'left_outer_join',
 'primary_key': 'STATE_NAME', 
 'source': {'cardinality': 'one_to_many',
            'destination': {'connection_info': {'database': 'C:\\Projects\\YosemiteNP\\Data\\BackgroundData.gdb'},
                            'dataset': 'census2010',                            
                            'workspace_factory': 'File Geodatabase'},
            'foreign_key': 'State_Name',            
            'join_forward': False,            
            'join_type': 'left_outer_join',            
            'primary_key': 'STATE_NAME',            
            'source': {'connection_info': {'database': 'C:\\Projects\\YosemiteNP\\Data\\BackgroundData.gdb'},
                       'dataset': 'State_Polygons',                       
                       'workspace_factory': 'File Geodatabase'}}}

连接与图层或表相关时,connectionProperties 字典结构将更改。 您将不再具有与之前示例中所看到的相同的三个根级别键。 要了解其不同的原因,您需要了解保存连接的方法。 连接是嵌套的。 例如,如果表一和表二都连接到图层,则表一连接到图层,而表二连接到该图层与表一的组合。 根级别字典首先描述第二个连接。 通过第二个连接的 source 可追踪与原始图层和表 1 的连接。

以下是使用具有连接的 connectionProperties 字典的示例:

  1. 以下示例将修改特定图层的连接的外键。

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\Mexico\MexicoEcology.aprx')
    mexLyr = aprx.listMaps('Layers')[0].listLayers('mex_eco')[0]
    conProps = mexLyr.connectionProperties
    conProps['foreign_key'] = 'ECO_CODE_NEW'
    mexLyr.updateConnectionProperties(mexLyr.connectionProperties, conProps)
    aprx.saveACopy(r"C:\Projects\Mexico\MexicoEcologyNew.aprx")
  2. 部分字典还可以用于 updateConnectionProperties 方法中。 以下示例将修改工程中使用指定外键的所有图层的连接属性:

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\Mexico\MexicoEcology.aprx')
    aprx.updateConnectionProperties({'foreign_key': 'ECO_CODE'}, {'foreign_key': 'ECO_CODE_NEW'})
    aprx.saveACopy(r"C:\Projects\Mexico\MexicoEcologyNew.aprx")
  3. 以下示例将针对两个表所连接到的主要图层修改源数据库和数据集,而不更改连接的连接信息:

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    lyr = aprx.listMaps("Main*")[0].listLayers("State_Polygons")[0]
    conProp = lyr.connectionProperties
    conProp['source']['source']['connection_info']['database'] = 'C:\\Projects\\YosemiteNP\\Vector_Data\\Census.gdb'
    conProp['source']['source']['dataset'] = 'States'
    lyr.updateConnectionProperties(lyr.connectionProperties, conProp)
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  4. 以下示例将创建地图中所有图层上所有连接的连接清单。 本示例采用 Python 递归函数逻辑来处理不具有连接或具有任意连接数的图层:

    import arcpy
    
    def ListJoinsConProp(cp, join_count=0):
        if 'source' in cp:
            if 'destination' in cp:
                print(' '*6, 'Join Properties:')
                print(' '*9, cp['destination']['connection_info'])
                print(' '*9, cp['destination']['dataset'])
                join_count += 1
                return ListJoinsConProp(cp['source'], join_count)
        else:
            if join_count == 0:
                print(' '*6, '- no join')
    
    aprx = arcpy.mp.ArcGISProject(r"C:\Projects\Mexico\MexicoEcology.aprx")
    m = aprx.listMaps()[0]
    for lyr in m.listLayers():
        print(f"LAYER: {lyr.name}")
        if lyr.supports("dataSource"):
            cp = lyr.connectionProperties
            if cp is not None:
                ListJoinsConProp(cp)
  5. 以下示例将显示地图中图层的连接属性。 与上面的示例类似,该示例还采用 Python 递归函数逻辑来处理不具有连接或具有任意连接数的图层:

    import arcpy
    
    def ConPropsWithJoins(cp):
        if 'source' in cp:
            return ConPropsWithJoins(cp['source'])
        else:
            print(' '*6, 'database:', cp['connection_info']['database'])
            print(' '*6, 'dataset:', cp['dataset'])
            print(' '*6, 'workspace_factory:', cp['workspace_factory'])
    
    aprx = arcpy.mp.ArcGISProject(r"C:\Projects\Mexico\MexicoEcology.aprx")
    m = aprx.listMaps()[0]
    for lyr in m.listLayers():
        print(f"LAYER: {lyr.name}")
        if lyr.supports("dataSource"):
            cp = lyr.connectionProperties
            if cp is not None:
                ConPropsWithJoins(cp)

使用 CIM 更新数据源

ArcGIS Pro 2.4 开始,Python 开发人员可以对制图信息模型 (CIM) 进行细化访问,并可以访问工程或文档中永久保留的更多设置、属性和功能。 这对于更新数据源工作流可能很有用。 有关详细信息,请参阅以下内容:

如果特定的数据源工作流难以使用 updateConnectionProperties 函数完成,则修改图层的 CIM 结构是一种选择。 Python CIM 访问 主题描述了 CIM 对象模型的 JSON 结构。 了解此结构将使您能够更新图层的 CIM。

例如,以下是文件地理数据库图层的数据源的 JSON 表示。 以下 JSON 不是图层的完整 CIM 结构。 而是一个仅显示 dataConnection 节点的片段。

"dataConnection" : {
  "type" : "CIMFeatureDatasetDataConnection",
  "workspaceConnectionString" : "DATABASE=C:\\Projects\\YosemiteNP\\Yosemite.gdb",
  "workspaceFactory" : "FileGDB",
  "dataset" : "Parcels",
  "datasetType" : "esriDTFeatureClass"
}

以下是一些使用 CIM 更新数据源的示例:

  1. 该脚本将更改图层上的关联的数据源。

    import arcpy
    
    # Specify the new relate properties
    newGDB = "FGDB2.gdb"
    newFeatureClass = "Cities2"
    newRelateName = "New Relate"
    
    # Reference project, map and layer 
    p = arcpy.mp.ArcGISProject(r'C:\Projects\USA.aprx')
    m = p.listMaps('Relate Map')[0]
    l = m.listLayers('States')[0]
    
    # Get the layer's CIM definition
    lyrCIM = l.getDefinition('V3')         
    
    # Get the first relate on the layer
    relate = lyrCIM.featureTable.relates[0]
    
    # Get the data connection properties for the relate
    dc = relate.dataConnection
    
    # Change the connection string to point to the new File Geodatabase
    dc.workspaceConnectionString = dc.workspaceConnectionString.replace("FGDB.gdb", newGDB)
    
    # Change the dataset name
    dc.dataset = newFeatureClass
        
    # Change the relate's name
    relate.name = newRelateName
    
    # Set the layer's CIM definition
    l.setDefinition(lyrCIM)
    
    p.saveACopy(r"C:\Projects\New\USA.aprx")
  2. 以下示例引用了地图中的 CAD 图层。 然后,将更新图层以指向新的 CAD 文件。 该脚本假定新的 CAD 文件与先前的 CAD 文件位于同一文件夹中。

    注:

    为 CAD 图层更新数据源以指向新的 CAD 文件需要修改 CIM。 但是,仅更改 CAD 文件所在的文件夹可以使用 updateConnectionProperties 函数完成。

    import arcpy
    
    aprx = arcpy.mp.ArcGISProject(r"C:\Projects\YosemiteNP\Yosemite.aprx")
    m = aprx.listMaps('CAD')[0]
    # Select the CAD sub layer to update
    lyr = m.listLayers('Parcels')[0]
    
    # Access layer CIM
    lyrCIM = lyr.getDefinition("V3")
    dc = lyrCIM.featureTable.dataConnection
    
    # Update the feature dataset with the new CAD file name 
    dc.featureDataset = "NewParcels.dwg"
    
    # Update layer CIM
    lyr.setDefinition(lyrCIM)
    
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  3. 以下示例通过将现有的 SQL where 子句替换为新的 where 子句来更新查询图层的 SQL 查询。

    注:

    此示例仅替换 SQL where 子句中的一个值。 如果您要添加或移除 SQL 字段,则还需要相应地更新 featureTable.dataConnection.queryFields 列表。

    import arcpy
    
    # Reference project, map and layer 
    p = arcpy.mp.ArcGISProject(r'C:\Projects\USA.aprx')
    m = p.listMaps('USA')[0]
    l = m.listLayers('States')[0]
    
    # Get the layer's CIM definition
    lyrCIM = l.getDefinition('V3')         
    
    # Update the sql query where clause for the layer
    sql = lyrCIM.featureTable.dataConnection.sqlQuery
    newsql = sql.replace("WHERE SUB_REGION = 'Mtn'", "WHERE SUB_REGION = 'Pacific'")
    lyrCIM.featureTable.dataConnection.sqlQuery = newsql
        
    # Set the layer's CIM definition
    l.setDefinition(lyrCIM)
    
    p.saveACopy(r'C:\Projects\USA_New.aprx')

更改图层的数据集

在某些情况下,需要将图层的数据源更改为具有其他名称的要素类。 例如,数据库方案已更改或要素类更新为具有新名称。 可通过两种方式实现此目的:

  • 使用 LayerTable 类中的可用 connectionProperties 字典。
  • 使用 python CIM 访问。

使用 connectionProperties 字典更改图层的数据集

  1. 以下示例将数据源的数据集名称从 RangerStations 更新为 RangerStationsNew。 它还将地理数据库从 Yosemite.gdb 更新为 YosemiteNew.gdb

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    lyr = aprx.listMaps("Main*")[0].listLayers("Ranger Stations")[0]
    find_dict = {'connection_info': {'database': 'C:\\Projects\\YosemiteNP\\Data\\Yosemite.gdb'}, 
                 'dataset': 'RangerStations', 
                 'workspace_factory': 'File Geodatabase'}
    replace_dict = {'connection_info': {'database': 'C:\\Projects\\YosemiteNP\\Data\\YosemiteNew.gdb'}, 
                    'dataset': 'RangerStationsNew', 
                    'workspace_factory': 'File Geodatabase'}
    lyr.updateConnectionProperties(find_dict, replace_dict)
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  2. 以下示例针对工程中的图层将数据源的数据集名称从 PtsInterest 更新为 PointsOfInterest。 本示例不会更改要素类所在的地理数据库。 更确切的说,它会使用部分字典将图层更新为指向同一地理数据库中的其他要素类。

    import arcpy
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    aprx.updateConnectionProperties({'dataset': 'PtsInterest'}, {'dataset': 'PointsOfInterest'})
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  3. 在以下示例中,将在引用特定要素类的工程中搜索图层。 然后将数据源的数据集名称从 PtsInterest 更新为 PointsOfInterest

    import arcpy
    
    oldDataset = 'PtsInterest'
    newDataset = 'PointsOfInterest'
    fGDB = r'C:\Projects\YosemiteNP\Yosemite.gdb'
    
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    
    for m in aprx.listMaps():
        for lyr in m.listLayers():
            if lyr.supports("DATASOURCE"):
                if lyr.dataSource == os.path.join(fGDB, oldDataset):
                    lyr.updateConnectionProperties({'dataset': oldDataset}, {'dataset': newDataset})
                    
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")

使用 CIM 更改图层数据集

  1. 此脚本会将图层数据集更新为同一地理数据库中的新要素类。

    import arcpy
    
    newFeatureClass = "UpdatedBoundary"
    
    # Reference project, map and layer 
    p = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    m = p.listMaps('Park Map')[0]
    l = m.listLayers('Boundary')[0]
    
    # Get the layer's CIM definition
    lyrCIM = l.getDefinition('V3')         
    
    # Update the dataset
    lyrCIM.featureTable.dataConnection.dataset = newFeatureClass
        
    # Set the layer's CIM definition
    l.setDefinition(lyrCIM)
    
    p.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  2. 此脚本会在已重命名的特定要素类的工程中搜索所有已损坏图层。 然后将图层数据源更新为新要素类。

    import arcpy
    
    newFeatureClass = "UpdatedBoundary"
    
    # Reference project
    aprx = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    
    # Search for specific broken layers
    for m in aprx.listMaps():
        for lyr in m.listBrokenDataSources():
            if lyr.supports("DATASOURCE"):
                if lyr.dataSource == r'C:\Projects\YosemiteNP\Yosemite.gdb\Boundary':
                    # Get the layer's CIM definition
                    lyrCIM = lyr.getDefinition('V3')         
                    # Update the dataset
                    lyrCIM.featureTable.dataConnection.dataset = newFeatureClass
                    # Set the layer's CIM definition
                    lyr.setDefinition(lyrCIM)
    
    aprx.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  3. 该脚本将更改图层的数据源,其中要素类和要素数据集名称在现有地理数据库和新地理数据库中不同。

    import arcpy
    
    # Specify the new geodatabase properties
    newGDB = "UpdatedParcels.gdb"
    newFeatureClass = "UpdatedParcelsFC"
    newFeatureDataSet = "UpdatedParcelsFDS"
    
    # Reference project, map and layer 
    p = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    m = p.listMaps('Parcels Map')[0]
    l = m.listLayers('Parcels')[0]
    
    # Get the layer's CIM definition
    lyrCIM = l.getDefinition('V3')         
    
    # Get the data connection properties for the layer
    dc = lyrCIM.featureTable.dataConnection
    
    # Change the connection string to point to the new File Geodatabase
    dc.workspaceConnectionString = dc.workspaceConnectionString.replace("Parcels.gdb", newGDB)
    
    # Change the dataset name
    dc.dataset = newFeatureClass
    
    # If the data is in a Feature Dataset, then update it 
    if hasattr(dc, "featureDataset"):
        dc.featureDataset = newFeatureDataSet
        
    # Set the layer's CIM definition
    l.setDefinition(lyrCIM)
    
    p.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")
  4. 在一些工作流中,新数据源的 CIM 结构与现有结构不同,需要您创建新的 CIM 数据连接对象。 在此示例中,不在要素数据集中的图层将更新为引用要素数据集中的要素类。 这需要创建新的 CIM 数据连接对象,因为要素数据集属性不在现有图层的 CIM 结构中。 请注意,您不必在代码中明确设置要素数据集属性。 仅需指定要素类,要素数据集即可自动填充。 同一代码可用于将位于要素数据集中的图层的数据源更新为不在要素数据集中的要素类。

    import arcpy
    
    # Specify the new geodatabase properties
    newGDB = r'C:\Projects\Data\NewParcels.gdb'
    newFeatureClass = "UpdatedParcelsFC"
    
    # Reference project, map and layer 
    p = arcpy.mp.ArcGISProject(r'C:\Projects\YosemiteNP\Yosemite.aprx')
    m = p.listMaps('Parcels Map')[0]
    l = m.listLayers('Parcels')[0]
    
    # Get the layer's CIM definition
    lyrCIM = l.getDefinition('V3')         
    
    # Create a new CIM data connection
    dc = arcpy.cim.CreateCIMObjectFromClassName('CIMStandardDataConnection', 'V3')
    
    # Specify the geodatabase
    dc.workspaceConnectionString = f"DATABASE={newGDB}"
    
    # Specify the workspace type
    dc.workspaceFactory = "FileGDB"
    
    # Specify the dataset name
    dc.dataset = newFeatureClass
    
    # Set the new data connection to the layer's CIM featureTable
    lyrCIM.featureTable.dataConnection = dc
        
    # Set the layer's CIM definition
    l.setDefinition(lyrCIM)
    
    p.saveACopy(r"C:\Projects\YosemiteNP\YosemiteNew.aprx")