Sao chép cơ sở dữ liệu địa lý ArcSDE để tập tin cơ sở dữ liệu địa lý bằng ArcPy?


9

Tôi muốn tạo một bản sao chính xác (tên miền, bộ dữ liệu tính năng, lớp tính năng, v.v.) của cơ sở dữ liệu SDE sang cơ sở dữ liệu địa lý tệp.

Tôi đã thử một số khả năng, bao gồm:

  1. sử dụng quy trình Sao chép (Quản lý dữ liệu)
  2. tạo một GDB mới và sao chép thủ công từng bộ dữ liệu tính năng từ SDE
  3. xuất tài liệu không gian làm việc xml từ SDE và nhập nó vào GDB

Các Copy_managementquá trình không có vẻ như nó sẽ làm việc để sao chép một SDE đến một GDB, vì đầu vào và đầu ra kiểu dữ liệu phải phù hợp.

Quá trình nhập từng tập dữ liệu tính năng vào GDB mới có thể được tự động hóa bằng cách sử dụng Copy_man quản lý bằng cách lặp qua từng tập dữ liệu tính năng, mặc dù có vẻ như điều này có thể gây ra sự cố của một bản sao không hoàn chỉnh nếu có lỗi với một trong các quy trình.

Xuất và nhập không gian làm việc xml dường như hoạt động, mặc dù quá trình này tạo ra các tệp lớn đến mức khó tin khi quy trình được sử dụng trên cơ sở dữ liệu địa lý lớn.

Có cách nào đơn giản hơn để sao chép nội dung và lược đồ của SDE sang GDB so với các cách được đề cập, theo cách có thể được tự động hóa không?

Nếu không, có bất kỳ lý do mà các khả năng trên không nên được sử dụng trong quá trình này?


Câu trả lời:


5

Cách duy nhất bạn có thể có được một bản sao thực sự của dữ liệu (tên miền, bộ dữ liệu, mối quan hệ, v.v.) là sử dụng phương pháp sao chép và dán thủ công trong danh mục. ESRI chưa cung cấp cho chúng tôi khả năng chuyển dữ liệu này qua bất kỳ cách nào khác với một thao tác có thể được viết kịch bản dễ dàng.

Tôi có một quy trình hàng đêm sao chép hai Cơ sở dữ liệu SDE chính của mình để gửi cơ sở dữ liệu địa lý cho Hoạt động liên tục. Điều này là để trong trường hợp khẩn cấp, nhân viên của tôi có một số dữ liệu để làm việc cho đến khi cửa hàng CNTT của tôi có thể xây dựng lại SDE của tôi từ bản sao lưu. Sau nhiều thử nghiệm và lỗi, tôi đã quyết định rằng chúng ta có thể sống với những hạn chế của việc sử dụng FeatureClassToFeatureClass_conversionTableToTable_conversion để chuyển dữ liệu của chúng tôi mỗi đêm.

Có, chúng tôi mất một số chức năng của cơ sở dữ liệu địa lý nhưng giờ đây nó sẽ chạy không cần giám sát vào ban đêm và sẵn sàng hoạt động ngay khi tôi nhận được. Trong trường hợp của tôi, chức năng duy nhất mà chúng tôi thực sự bị thiếu (giả sử hoạt động ở chế độ khẩn cấp) là các lớp mối quan hệ của tôi bị hỏng vì chuyển đổi đặt lại các ObjectID liên kết hai bảng.

Cho đến khi ESRI cung cấp cho chúng tôi nhiều lựa chọn hơn, bạn sẽ phải xem xét những gì bạn sẵn sàng hy sinh vào lúc này; Thời gian và công sức hay chức năng?


Một tài liệu worskspace xml sẽ không hoạt động?
Jyler

8

Tôi biết bài đăng này hơi cũ nhưng tôi mặc dù tôi sẽ chia sẻ câu trả lời của mình vì tôi phải đối mặt với cùng một vấn đề. Tập lệnh sau NÊN sao chép tất cả các bảng, các lớp đối tượng và các mối quan hệ không có trong tập dữ liệu và cũng sẽ sao chép trên tất cả các tập dữ liệu bao gồm các lớp đối tượng, cấu trúc liên kết, v.v. trong tập dữ liệu. Nó sẽ bỏ qua bất kỳ lỗi nào trong quá trình sao chép adn tiếp tục. Nó sẽ tạo ra một tệp nhật ký chứa dữ liệu như số lượng mục DB nguồn và số mục đích để bạn có thể so sánh bản sao và nó cũng sẽ ghi lại các lỗi mà nó gặp phải.

import arcpy, os, shutil, time
import logging as log
from datetime import datetime

def formatTime(x):
    minutes, seconds_rem = divmod(x, 60)
    if minutes >= 60:
        hours, minutes_rem = divmod(minutes, 60)
        return "%02d:%02d:%02d" % (hours, minutes_rem, seconds_rem)
    else:
        minutes, seconds_rem = divmod(x, 60)
        return "00:%02d:%02d" % (minutes, seconds_rem)

def getDatabaseItemCount(workspace):
    arcpy.env.workspace = workspace
    feature_classes = []
    for dirpath, dirnames, filenames in arcpy.da.Walk(workspace,datatype="Any",type="Any"):
        for filename in filenames:
            feature_classes.append(os.path.join(dirpath, filename))
    return feature_classes, len(feature_classes)

def replicateDatabase(dbConnection, targetGDB):
    startTime = time.time()

    featSDE,cntSDE = getDatabaseItemCount(dbConnection)
    featGDB,cntGDB = getDatabaseItemCount(targetGDB)

    now = datetime.now()
    logName = now.strftime("SDE_REPLICATE_SCRIPT_%Y-%m-%d_%H-%M-%S.log")
    log.basicConfig(datefmt='%m/%d/%Y %I:%M:%S %p', format='%(asctime)s %(message)s',\
    filename=logName,level=log.INFO)

    print "Old Target Geodatabase: %s -- Feature Count: %s" %(targetGDB, cntGDB)
    log.info("Old Target Geodatabase: %s -- Feature Count: %s" %(targetGDB, cntGDB))
    print "Geodatabase being copied: %s -- Feature Count: %s" %(dbConnection, cntSDE)
    log.info("Geodatabase being copied: %s -- Feature Count: %s" %(dbConnection, cntSDE))

    arcpy.env.workspace = dbConnection

    #deletes old targetGDB
    try:
        shutil.rmtree(targetGDB)
        print "Deleted Old %s" %(os.path.split(targetGDB)[-1])
        log.info("Deleted Old %s" %(os.path.split(targetGDB)[-1]))
    except Exception as e:
        print e
        log.info(e)

    #creates a new targetGDB
    GDB_Path, GDB_Name = os.path.split(targetGDB)
    print "Now Creating New %s" %(GDB_Name)
    log.info("Now Creating New %s" %(GDB_Name))
    arcpy.CreateFileGDB_management(GDB_Path, GDB_Name)

    datasetList = [arcpy.Describe(a).name for a in arcpy.ListDatasets()]
    featureClasses = [arcpy.Describe(a).name for a in arcpy.ListFeatureClasses()]
    tables = [arcpy.Describe(a).name for a in arcpy.ListTables()]

    #Compiles a list of the previous three lists to iterate over
    allDbData = datasetList + featureClasses + tables

    for sourcePath in allDbData:
        targetName = sourcePath.split('.')[-1]
        targetPath = os.path.join(targetGDB, targetName)
        if arcpy.Exists(targetPath)==False:
            try:
                print "Atempting to Copy %s to %s" %(targetName, targetPath)
                log.info("Atempting to Copy %s to %s" %(targetName, targetPath))
                arcpy.Copy_management(sourcePath, targetPath)
                print "Finished copying %s to %s" %(targetName, targetPath)
                log.info("Finished copying %s to %s" %(targetName, targetPath))
            except Exception as e:
                print "Unable to copy %s to %s" %(targetName, targetPath)
                print e
                log.info("Unable to copy %s to %s" %(targetName, targetPath))
                log.info(e)
        else:
            print "%s already exists....skipping....." %(targetName)
            log.info("%s already exists....skipping....." %(targetName))
    featGDB,cntGDB = getDatabaseItemCount(targetGDB)
    print "Completed replication of %s -- Feature Count: %s" %(dbConnection, cntGDB)
    log.info("Completed replication of %s -- Feature Count: %s" %(dbConnection, cntGDB))
    totalTime = (time.time() - startTime)
    totalTime = formatTime(totalTime)
    log.info("Script Run Time: %s" %(totalTime))

if __name__== "__main__":
    databaseConnection = r"YOUR_SDE_CONNECTION"
    targetGDB = "DESTINATION_PATH\\SDE_Replicated.gdb"
    replicateDatabase(databaseConnection, targetGDB)   

Tôi đã thực sự may mắn với điều này. Tôi đã sao chép cơ sở dữ liệu SDE sang cơ sở dữ liệu địa lý tệp. Tôi đã không thực hiện quá nhiều thử nghiệm trên kịch bản này mặc dù nó đã đáp ứng mọi nhu cầu của tôi. Tôi đã thử nghiệm nó bằng ArcGIS 10.3. Ngoài ra, một điều cần lưu ý, tôi đã nói chuyện với ai đó đã sử dụng tập lệnh này và họ gặp phải một vấn đề với lỗi sao chép bộ dữ liệu nhất định do quyền không phù hợp và bảng trống.

Lemur - tại sao không tạo mối quan hệ của bạn dựa trên id toàn cầu thay vì id đối tượng? Rằng các mối quan hệ của bạn sẽ được bảo tồn. Nếu bạn chưa tạo id toàn cầu, tôi rất muốn giới thiệu nó.

-tập nhật

Tôi đã thêm một chút logic vào mã để xử lý các đường dẫn kết nối cơ sở dữ liệu xấu và xử lý lỗi và ghi nhật ký tốt hơn:

import time, os, datetime, sys, logging, logging.handlers, shutil
import arcpy

########################## user defined functions ##############################

def getDatabaseItemCount(workspace):
    log = logging.getLogger("script_log")
    """returns the item count in provided database"""
    arcpy.env.workspace = workspace
    feature_classes = []
    log.info("Compiling a list of items in {0} and getting count.".format(workspace))
    for dirpath, dirnames, filenames in arcpy.da.Walk(workspace,datatype="Any",type="Any"):
        for filename in filenames:
            feature_classes.append(os.path.join(dirpath, filename))
    log.info("There are a total of {0} items in the database".format(len(feature_classes)))
    return feature_classes, len(feature_classes)

def replicateDatabase(dbConnection, targetGDB):
    log = logging.getLogger("script_log")
    startTime = time.time()

    if arcpy.Exists(dbConnection):
        featSDE,cntSDE = getDatabaseItemCount(dbConnection)
        log.info("Geodatabase being copied: %s -- Feature Count: %s" %(dbConnection, cntSDE))
        if arcpy.Exists(targetGDB):
            featGDB,cntGDB = getDatabaseItemCount(targetGDB)
            log.info("Old Target Geodatabase: %s -- Feature Count: %s" %(targetGDB, cntGDB))
            try:
                shutil.rmtree(targetGDB)
                log.info("Deleted Old %s" %(os.path.split(targetGDB)[-1]))
            except Exception as e:
                log.info(e)

        GDB_Path, GDB_Name = os.path.split(targetGDB)
        log.info("Now Creating New %s" %(GDB_Name))
        arcpy.CreateFileGDB_management(GDB_Path, GDB_Name)

        arcpy.env.workspace = dbConnection

        try:
            datasetList = [arcpy.Describe(a).name for a in arcpy.ListDatasets()]
        except Exception, e:
            datasetList = []
            log.info(e)
        try:
            featureClasses = [arcpy.Describe(a).name for a in arcpy.ListFeatureClasses()]
        except Exception, e:
            featureClasses = []
            log.info(e)
        try:
            tables = [arcpy.Describe(a).name for a in arcpy.ListTables()]
        except Exception, e:
            tables = []
            log.info(e)

        #Compiles a list of the previous three lists to iterate over
        allDbData = datasetList + featureClasses + tables

        for sourcePath in allDbData:
            targetName = sourcePath.split('.')[-1]
            targetPath = os.path.join(targetGDB, targetName)
            if not arcpy.Exists(targetPath):
                try:
                    log.info("Atempting to Copy %s to %s" %(targetName, targetPath))
                    arcpy.Copy_management(sourcePath, targetPath)
                    log.info("Finished copying %s to %s" %(targetName, targetPath))
                except Exception as e:
                    log.info("Unable to copy %s to %s" %(targetName, targetPath))
                    log.info(e)
            else:
                log.info("%s already exists....skipping....." %(targetName))

        featGDB,cntGDB = getDatabaseItemCount(targetGDB)
        log.info("Completed replication of %s -- Feature Count: %s" %(dbConnection, cntGDB))

    else:
        log.info("{0} does not exist or is not supported! \
        Please check the database path and try again.".format(dbConnection))

#####################################################################################

def formatTime(x):
    minutes, seconds_rem = divmod(x, 60)
    if minutes >= 60:
        hours, minutes_rem = divmod(minutes, 60)
        return "%02d:%02d:%02d" % (hours, minutes_rem, seconds_rem)
    else:
        minutes, seconds_rem = divmod(x, 60)
        return "00:%02d:%02d" % (minutes, seconds_rem)

if __name__ == "__main__":
    startTime = time.time()
    now = datetime.datetime.now()

    ############################### user variables #################################
    '''change these variables to the location of the database being copied, the target 
    database location and where you want the log to be stored'''

    logPath = ""
    databaseConnection = "path_to_sde_or_gdb_database"
    targetGDB = "apth_to_replicated_gdb\\Replicated.gdb"

    ############################### logging items ###################################
    # Make a global logging object.
    logName = os.path.join(logPath,(now.strftime("%Y-%m-%d_%H-%M.log")))

    log = logging.getLogger("script_log")
    log.setLevel(logging.INFO)

    h1 = logging.FileHandler(logName)
    h2 = logging.StreamHandler()

    f = logging.Formatter("[%(levelname)s] [%(asctime)s] [%(lineno)d] - %(message)s",'%m/%d/%Y %I:%M:%S %p')

    h1.setFormatter(f)
    h2.setFormatter(f)

    h1.setLevel(logging.INFO)
    h2.setLevel(logging.INFO)

    log.addHandler(h1)
    log.addHandler(h2)

    log.info('Script: {0}'.format(os.path.basename(sys.argv[0])))

    try:
        ########################## function calls ######################################

        replicateDatabase(databaseConnection, targetGDB)

        ################################################################################
    except Exception, e:
        log.exception(e)

    totalTime = formatTime((time.time() - startTime))
    log.info('--------------------------------------------------')
    log.info("Script Completed After: {0}".format(totalTime))
    log.info('--------------------------------------------------')

Peter, tôi đã sử dụng tập lệnh mà bạn cung cấp và tôi đã cập nhật 2 biến ở phía dưới. Tôi đang gặp lỗi TracBack (cuộc gọi gần đây nhất): Tệp "ServerPath \\ CopySDEtoGDB.py", dòng 90, trong <module> sao chép cơ sở dữ liệu sao chép dữ liệu cơ sở dữ liệuList = [arcpy.Describe (a) .name cho a trong arcpy.ListDatasets ()] TypeError: đối tượng 'noneType' không thể lặp lại Bất kỳ đầu mối nào có nghĩa là gì?
Courtney

Courtney - Có vẻ như có một lỗi đánh máy hoặc một lỗi nhỏ trong đường dẫn đến biến kết nối cơ sở dữ liệu của bạn. Nó đang báo lỗi vì nó đang cố lặp lại một danh sách trống trên dòng 55. Tôi đã có thể tạo lại lỗi bạn gặp phải bằng cách sử dụng đường dẫn không chính xác trong biến "databaseConnection". con đường thực tế bạn đã sử dụng trong biến là gì?
PMK

Nếu tôi muốn làm điều này hàng đêm, nó sẽ không ghi đè lên các tính năng hiện có? Tôi không muốn tạo FGD mới mỗi lần tôi chỉ muốn ghi đè lên mục tiêu hiện có.
NULL.Dude

Peter nếu mục tiêu GDB tồn tại tập lệnh thất bại
NULL.Dude

2

Tôi đã sử dụng một kịch bản tương tự như Peter ở trên và đã gặp may mắn, mặc dù kịch bản của anh ấy tốt hơn. Một điều cần chỉ ra rằng có thể khiến ai đó gặp rắc rối là nếu bạn đang sử dụng công cụ địa lý python 64 bit và bạn đã tải ArcFM trên ESRI, nó sẽ thất bại trên tất cả các tính năng đã được đặt để sử dụng ArcFM hoặc Designer với ERROR 000260. Điều này là bởi vì bạn phải sử dụng python 32 bit hoặc công cụ ArcFM sẽ không được cấp phép đúng cách.

Để biết mô tả chi tiết hơn về việc sử dụng ArcPy 32 bit, hãy xem hai nhận xét đầu tiên về chủ đề này trong Exchange

https://infrastructurecommunity.schneider-electric.com/docs/DOC-2563


Nếu hai bình luận đó cung cấp câu trả lời cho câu hỏi này thì nội dung của chúng sẽ được trích dẫn hoặc tóm tắt tại đây và không chỉ liên kết với - xem meta.stackexchange.com/questions/225370/. Nếu bạn đã cung cấp một bản tóm tắt có lẽ chỉ cần thay đổi "Kiểm tra trong hai bình luận đầu tiên về chủ đề này trong Exchange "thành" Để biết mô tả chi tiết hơn, hãy xem hai bình luận đầu tiên về chủ đề này trong Exchange ".
PolyGeo

0

Nếu bạn có đặc quyền quản trị viên, bạn có thể sử dụng các lệnh sao chép và dán đơn giản để xuất hoặc nhập sde để gửi ngược lại cơ sở dữ liệu địa lý và xem tại đây để biết thêm chi tiết.


Cảm ơn Ganeshnarim - Tôi muốn tự động hóa quy trình bằng Python, vì vậy mọi quy trình sao chép / dán thủ công trong ArcCatalog sẽ không phù hợp với nhu cầu của tôi. Tôi cũng đã hạn chế thành công với phương pháp này, vì dường như (trong ArcMap 10.1) sao chép SDE chỉ đơn giản là tạo một liên kết khác đến cùng cơ sở dữ liệu (trong khi nếu kỹ thuật này được sử dụng trên một tệp hoặc cơ sở dữ liệu địa lý cá nhân, một bản sao sẽ được tạo ra)
Krausers
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.