กำลังคัดลอก ArcSDE Geodatabase ไปยังไฟล์ Geodatabase โดยใช้ ArcPy หรือไม่


9

ฉันต้องการทำสำเนาที่แน่นอน (โดเมน, ชุดข้อมูลคุณลักษณะ, คลาสคุณสมบัติ, ฯลฯ ) ของฐานข้อมูล SDE ไปยังฐานข้อมูลไฟล์

ฉันได้ลองหลายวิธีรวมถึง:

  1. ใช้กระบวนการคัดลอก (การจัดการข้อมูล)
  2. สร้าง GDB ใหม่และคัดลอกชุดข้อมูลแต่ละชุดด้วยตนเองจาก SDE
  3. ส่งออกเอกสารพื้นที่ทำงาน xml จาก SDE และนำเข้าสู่ GDB

Copy_managementกระบวนการไม่ได้ดูเหมือนว่ามันจะทำงานให้คัดลอก SDE ไป GDB ตั้งแต่ประเภท input และ output ข้อมูลจะต้องตรงกับ

กระบวนการนำเข้าชุดข้อมูลคุณลักษณะแต่ละชุดลงใน GDB ใหม่อาจเป็นไปโดยอัตโนมัติโดยใช้ Copy_management ด้วยการวนซ้ำผ่านชุดข้อมูลแต่ละชุด แต่ดูเหมือนว่านี่อาจทำให้เกิดปัญหาสำเนาที่ไม่สมบูรณ์หากมีข้อผิดพลาดกับกระบวนการใดกระบวนการหนึ่ง

การส่งออกและนำเข้าพื้นที่ทำงาน xml ดูเหมือนว่าจะทำงานได้แม้ว่ากระบวนการนี้จะสร้างไฟล์ขนาดใหญ่อย่างไม่น่าเชื่อเมื่อมีการใช้กระบวนการบนฐานข้อมูล Geod ขนาดใหญ่

มีวิธีที่ตรงไปตรงมามากขึ้นในการคัดลอกเนื้อหาและสคีมาของ SDE ไปยัง GDB มากกว่าวิธีที่กล่าวถึงในวิธีที่สามารถเป็นแบบอัตโนมัติได้หรือไม่?

ถ้าไม่มีเหตุผลใดที่ความเป็นไปได้ข้างต้นไม่ควรใช้ในกระบวนการนี้หรือไม่?


1
เกี่ยวข้อง: gis.stackexchange.com/q/63368/753
blah238

คำตอบ:


5

วิธีเดียวที่คุณจะได้รับสำเนาที่แท้จริงของข้อมูล (โดเมนชุดข้อมูลความสัมพันธ์ ฯลฯ ) คือการใช้วิธีการคัดลอกและวางด้วยตนเองภายในแคตตาล็อก ESRI ยังไม่ได้ให้ความสามารถแก่เราในการถ่ายโอนข้อมูลนี้ด้วยวิธีอื่นด้วยการดำเนินการเพียงครั้งเดียวที่สามารถเขียนสคริปต์ได้อย่างง่ายดาย

ฉันมีกระบวนการทุกคืนที่คัดลอกฐานข้อมูล SDE หลักสองรายการของฉันไปยังไฟล์ฐานข้อมูล Geod เพื่อความต่อเนื่องของการดำเนินงาน นี่คือในกรณีที่เกิดเหตุฉุกเฉินพนักงานของฉันมีข้อมูลบางอย่างที่จะทำงานกับจนกว่าร้านไอทีของฉันสามารถสร้าง SDE ของฉันใหม่จากการสำรองข้อมูล หลังจากการทดลองใช้และข้อผิดพลาดมากมายฉันได้ตัดสินใจแล้วว่าเราสามารถใช้ชีวิตกับข้อ จำกัด ของการใช้FeatureClassToFeatureClass_conversionและTableToTable_conversionเพื่อถ่ายโอนข้อมูลของเราทุกคืน

ใช่เราสูญเสียฟังก์ชันการทำงานบางส่วนของฐานข้อมูลทางภูมิศาสตร์ แต่ตอนนี้จะทำงานแบบอัตโนมัติในเวลากลางคืนและพร้อมที่จะไปทันทีที่ฉันได้รับ ในกรณีของฉันฟังก์ชันการทำงานเดียวที่เราขาดหายไปอย่างแท้จริง (สมมติว่าทำงานภายใต้โหมดฉุกเฉิน) คือคลาสความสัมพันธ์ของฉันใช้งานไม่ได้เนื่องจากการแปลงตั้งค่า ObjectID ที่เชื่อมโยงตารางทั้งสองใหม่

จนกว่า ESRI จะให้ทางเลือกเพิ่มเติมแก่คุณคุณจะต้องดูว่าคุณเต็มใจเสียสละอะไรในขณะนี้ เวลาและความพยายามหรือฟังก์ชั่น?


เอกสาร xml worskspace ไม่ทำงาน
Jyler

8

ฉันรู้ว่าโพสต์นี้เก่าไปหน่อย แต่ฉันก็อยากแบ่งปันคำตอบของฉันตั้งแต่ฉันเผชิญกับปัญหาเดียวกัน สคริปต์ต่อไปนี้ควรคัดลอกตารางทั้งหมดคลาสคุณลักษณะและความสัมพันธ์ที่ไม่ได้อยู่ในชุดข้อมูลและจะคัดลอกไปยังชุดข้อมูลทั้งหมดรวมถึงคลาสฟีเจอร์โทโพโลยีและอื่น ๆ ภายในชุดข้อมูล มันจะข้ามข้อผิดพลาดใด ๆ ที่เกิดขึ้นระหว่างการคัดลอกและดำเนินต่อไป มันจะสร้างไฟล์บันทึกที่มีข้อมูลเช่นจำนวนรายการฐานข้อมูลต้นทางและจำนวนรายการปลายทางเพื่อให้คุณสามารถเปรียบเทียบสำเนาและจะบันทึกข้อผิดพลาดที่พบเช่นกัน

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)   

ฉันโชคดีจริงๆกับสิ่งนี้ ฉันกำลังจำลองฐานข้อมูล SDE ไปยังฐานข้อมูลไฟล์ทางภูมิศาสตร์ ฉันไม่ได้ทำการทดสอบสคริปต์นี้อย่างกว้างขวางเกินไปเนื่องจากมันตอบสนองความต้องการทั้งหมดของฉันได้สำเร็จ ฉันทดสอบโดยใช้ ArcGIS 10.3 นอกจากนี้สิ่งหนึ่งที่ควรทราบฉันกำลังพูดคุยกับคนที่ใช้สคริปต์นี้และพวกเขาพบปัญหาข้อผิดพลาดในการคัดลอกชุดข้อมูลบางอย่างเนื่องจากสิทธิ์ที่ไม่เหมาะสมและตารางว่างเปล่า

ตัวลีเมอร์ - ทำไมไม่สร้างความสัมพันธ์ของคุณตามไอดีระดับโลกแทนที่จะเป็นออบเจ็กต์? ว่าความสัมพันธ์ของคุณจะได้รับการเก็บรักษาไว้ หากคุณยังไม่ได้สร้างรหัสประจำตัวฉันขอแนะนำอย่างยิ่ง

-update

ฉันเพิ่มตรรกะเล็กน้อยลงในรหัสเพื่อจัดการเส้นทางการเชื่อมต่อฐานข้อมูลที่ไม่ดีและการบันทึกที่ดีขึ้นและการจัดการข้อผิดพลาด:

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('--------------------------------------------------')

ปีเตอร์ฉันใช้สคริปต์ที่คุณให้ไว้และฉันได้อัปเดตตัวแปร 2 ตัวที่ด้านล่าง ฉันได้รับข้อผิดพลาด Traceback (การโทรล่าสุดครั้งล่าสุด): ไฟล์ "ServerPath \\ CopySDEtoGDB.py", บรรทัด 90, ใน <module> replicateDatabase ฐานข้อมูล (ฐานข้อมูลการเชื่อมต่อ, targetGDB) ไฟล์ "ServerPath \\ CopySDEtoGDB.py", บรรทัด 55, ใน replicateDatabase datasetList = [arcpy.Describe (a) .name สำหรับ a ใน arcpy.ListDatasets ()] TypeError: วัตถุ 'NoneType' ไม่สามารถใช้ซ้ำได้เบาะแสอะไรที่มีความหมายอย่างไร
Courtney

Courtney - ดูเหมือนว่ามีการพิมพ์ผิดหรือมีข้อผิดพลาดเล็กน้อยในเส้นทางไปยังตัวแปรการเชื่อมต่อฐานข้อมูลของคุณ มันกำลังโยนข้อผิดพลาดเนื่องจากพยายามทำซ้ำมากกว่ารายการที่ว่างเปล่าในบรรทัด 55 ฉันสามารถสร้างข้อผิดพลาดที่คุณได้รับใหม่โดยใช้เส้นทางที่ไม่ถูกต้องในตัวแปร "databaseConnection" เส้นทางจริงที่คุณใช้ในตัวแปรคืออะไร?
PMK

ถ้าฉันต้องการที่จะทำคืนนี้มันจะไม่เขียนทับคุณสมบัติที่มีอยู่? ฉันไม่ต้องการสร้าง FGD ใหม่ทุกครั้งที่ฉันต้องการเขียนทับเป้าหมายที่มีอยู่
NULL.Dude

ปีเตอร์ถ้าเป้าหมายของ GDB มีอยู่สคริปต์จะล้มเหลว
NULL.Dude

2

ฉันใช้สคริปต์คล้ายกับของปีเตอร์ด้านบนและมีโชคดีแม้ว่าเขาจะดีกว่า สิ่งหนึ่งที่ชี้ให้เห็นว่าอาจทำให้ใครบางคนกำลังเดินทางคือถ้าคุณใช้การประมวลผลหลามแบบ 64 บิตและคุณมี ArcFM ที่โหลดอยู่ด้านบนของ ESRI มันจะล้มเหลวในฟีเจอร์ทั้งหมดที่ตั้งค่าให้ใช้ ArcFM หรือ Designer กับ ERROR 000260 เป็นเพราะคุณต้องใช้ python 32 บิตมิฉะนั้นสิ่ง ArcFM จะไม่ได้รับอนุญาตอย่างถูกต้อง

สำหรับคำอธิบายโดยละเอียดเพิ่มเติมของการใช้ ArcPy 32 บิตให้ดูความคิดเห็นสองข้อแรกในเธรดนี้ในการแลกเปลี่ยน

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


หากความคิดเห็นทั้งสองนั้นให้คำตอบสำหรับคำถามนี้เนื้อหาของพวกเขาควรจะอ้างถึงหรือสรุปที่นี่และไม่เพียง แต่เชื่อมโยงกับ - ดูmeta.stackexchange.com/questions/225370/ หากคุณได้ให้ข้อมูลสรุปแล้วอาจเพียงแค่เปลี่ยน "ตรวจสอบ แสดงความคิดเห็นสองครั้งแรกในหัวข้อนี้ในการแลกเปลี่ยน "เป็น" สำหรับคำอธิบายโดยละเอียดเพิ่มเติมดูความคิดเห็นสองข้อแรกในหัวข้อนี้ในการแลกเปลี่ยน "
PolyGeo

0

หากคุณมีสิทธิ์ผู้ดูแลระบบคุณสามารถใช้สำเนาง่ายและวางคำสั่งเพื่อการส่งออกหรือนำเข้า SDE ไปยังแฟ้มหนีบทางภูมิศาสตร์ฐานข้อมูลในทางกลับกันและขอให้ดูที่นี่สำหรับรายละเอียดเพิ่มเติม


ขอบคุณ Ganeshnarim - ฉันต้องการทำให้กระบวนการเป็นอัตโนมัติโดยใช้ Python ดังนั้นกระบวนการคัดลอก / วางด้วยตนเองใน ArcCatalog จะไม่ตรงกับความต้องการของฉัน ฉันยังประสบความสำเร็จอย่าง จำกัด ด้วยวิธีนี้ตามที่ดูเหมือน (ใน ArcMap 10.1) การคัดลอก SDE เพียงแค่สร้างลิงค์อื่นไปยังฐานข้อมูลเดียวกัน (ในขณะที่ถ้าใช้เทคนิคเดียวกันนี้ในไฟล์หรือฐานข้อมูลส่วนบุคคลจะทำการคัดลอก)
Krausers
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.