Menyalin geodatabase ArcSDE ke file geodatabase menggunakan ArcPy?

9

Saya ingin membuat salinan yang tepat (domain, kumpulan data fitur, kelas fitur, dll.) Dari basis data SDE ke geodatabase file.

Saya telah mencoba beberapa kemungkinan, termasuk:

  1. menggunakan proses Salin (Manajemen Data)
  2. membuat GDB baru dan secara manual menyalin setiap dataset fitur dari SDE
  3. mengekspor dokumen ruang kerja xml dari SDE dan mengimpornya ke GDB

The Copy_managementProses tidak tampak seperti itu akan bekerja untuk menyalin SDE ke GDB, karena input dan output tipe data harus cocok.

Proses mengimpor setiap dataset fitur ke GDB baru mungkin dapat diotomatisasi menggunakan Copy_management juga dengan mengulangi setiap dataset fitur, meskipun tampaknya ini dapat menyebabkan masalah salinan yang tidak lengkap jika ada kesalahan dengan salah satu proses.

Mengekspor dan mengimpor ruang kerja xml tampaknya berhasil, meskipun proses ini menciptakan file yang sangat besar ketika proses tersebut digunakan pada geodatabases besar.

Apakah ada cara yang lebih mudah untuk menyalin konten dan skema SDE ke GDB daripada cara yang disebutkan, dengan cara yang bisa otomatis?

Jika tidak, adakah alasan bahwa kemungkinan di atas tidak boleh digunakan dalam proses ini?

Krausers
sumber

Jawaban:

5

Satu-satunya cara Anda bisa mendapatkan salinan data yang benar (domain, kumpulan data, hubungan, dll) adalah dengan menggunakan metode salin dan tempel manual di dalam katalog. ESRI belum memberi kami kemampuan untuk mentransfer data ini dengan cara lain dengan satu operasi yang dapat dituliskan dengan mudah.

Saya memiliki proses malam yang menyalin dua Database SDE utama saya ke file geodatabases untuk Continuity of Operations. Hal ini dimaksudkan agar dalam keadaan darurat staf saya memiliki beberapa data untuk dikerjakan sampai toko IT saya dapat membangun kembali SDE saya dari cadangan. Setelah banyak percobaan dan kesalahan saya telah memutuskan kita dapat hidup dengan keterbatasan menggunakan FeatureClassToFeatureClass_conversion dan TableToTable_conversion untuk mentransfer data kami setiap malam.

Ya, kami kehilangan beberapa fungsi dari geodatabase tetapi sekarang akan berjalan tanpa pengawasan di malam hari dan siap untuk pergi segera setelah saya mendapatkannya. Dalam kasus saya, satu-satunya fungsi yang benar-benar kami lewatkan (dengan asumsi beroperasi dalam mode darurat) adalah bahwa kelas hubungan saya rusak karena konversi mengatur ulang ObjectIDs yang menautkan kedua tabel.

Sampai ESRI memberi kami lebih banyak opsi, Anda harus melihat apa yang ingin Anda korbankan saat ini; waktu dan usaha atau fungsionalitas?

Pukang
sumber
Dokumen xs worskspace xml tidak berfungsi?
Jyler
8

Saya tahu posting ini agak tua tapi saya pikir saya akan membagikan jawaban saya karena saya dihadapkan dengan masalah yang sama. Script berikut HARUS menyalin semua tabel, kelas fitur dan hubungan tidak dalam dataset dan juga akan menyalin semua dataset termasuk kelas fitur, topologi, dll dalam dataset. Ini akan melompati kesalahan apa pun selama copy dan terus berjalan. Ini akan menghasilkan file log yang berisi data seperti hitungan item sumber DB dan jumlah item tujuan sehingga Anda dapat membandingkan salinan dan itu akan mencatat kesalahan yang ditemui juga.

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)   

Saya sangat beruntung dengan ini. Saya mereplikasi database SDE ke file geodatabase. Saya belum melakukan pengujian yang terlalu luas pada skrip ini karena memenuhi semua kebutuhan saya. Saya mengujinya menggunakan ArcGIS 10.3. Juga, satu hal yang perlu diperhatikan, saya sedang dalam pembicaraan dengan seseorang yang telah menggunakan skrip ini dan mereka mengalami masalah dengan kesalahan menyalin dataset tertentu karena izin yang tidak tepat dan tabel kosong.

Lemur - mengapa tidak membuat hubungan Anda berdasarkan id global alih-alih id objek? Bahwa Anda, hubungan Anda akan dipertahankan. Jika Anda belum membuat id global, saya akan sangat merekomendasikannya.

-memperbarui

Saya menambahkan sedikit lebih banyak logika ke dalam kode untuk menangani jalur koneksi database yang buruk dan logging yang lebih baik dan penanganan kesalahan:

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('--------------------------------------------------')
PMK
sumber
Peter, saya menggunakan skrip yang Anda berikan dan saya memperbarui 2 variabel di bagian bawah. Saya mendapatkan pesan kesalahan Traceback (panggilan terakhir terakhir): File "ServerPath \\ CopySDEtoGDB.py", baris 90, dalam <module> replicateDatabase (databaseConnection, targetGDB) File "ServerPath \\ CopySDEtoGDB.py", baris 55, di replicateDatabase datasetList = [arcpy.Describe (a) .name untuk a di arcpy.ListDatasets ()] TypeError: objek 'NoneType' tidak dapat diubah Adakah petunjuk apa artinya ini?
Courtney
Courtney - Sepertinya ada kesalahan ketik atau sedikit kesalahan di jalur ke variabel koneksi database Anda. Itu melempar kesalahan karena mencoba untuk mengulangi daftar yang kosong pada baris 55. Saya bisa membuat ulang kesalahan yang Anda dapatkan dengan menggunakan jalur yang salah dalam variabel "databaseConnection". apa jalur aktual yang Anda gunakan dalam variabel?
PMK
Jika saya ingin melakukan ini setiap malam, itu tidak akan menimpa fitur yang ada? Saya tidak ingin membuat FGD baru setiap kali saya hanya ingin menimpa target yang ada.
NULL. Bung
Peter jika target GDB ada skrip gagal
NULL.Dude
2

Saya telah menggunakan skrip yang mirip dengan Peter di atas dan beruntung, meskipun itu lebih baik. Satu hal yang menunjukkan bahwa seseorang mungkin tersandung adalah jika Anda menggunakan 64 bit python geoprocessing dan Anda memiliki ArcFM dimuat di atas ESRI, itu akan gagal pada semua fitur yang telah ditetapkan untuk menggunakan ArcFM atau Designer dengan KESALAHAN 000260. Ini karena Anda harus menggunakan python 32 bit atau hal-hal ArcFM tidak akan dilisensikan dengan benar.

Untuk deskripsi lebih rinci tentang menggunakan 32 bit ArcPy, lihat dua komentar pertama pada utas ini di Exchange

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

rrankman
sumber
Jika kedua komentar itu memberikan jawaban untuk pertanyaan ini, maka isinya harus dikutip atau dirangkum di sini dan tidak hanya ditautkan ke - lihat meta.stackexchange.com/questions/225370/… Jika Anda sudah memberikan ringkasan, mungkin cukup ubah "Periksa keluar dua komentar pertama pada utas ini di Exchange "ke" Untuk deskripsi yang lebih rinci lihat dua komentar pertama pada utas ini di Exchange ".
PolyGeo
0

Jika Anda memiliki hak admin, Anda dapat menggunakan perintah salin dan rekat sederhana untuk mengekspor atau mengimpor sde ke file geo-database vise versa dan Lihat di sini untuk detail lebih lanjut.

Ganeshnarim
sumber
Terima kasih Ganeshnarim - Saya ingin mengotomatiskan proses menggunakan Python, sehingga proses salin / tempel manual di ArcCatalog tidak akan sesuai dengan kebutuhan saya. Saya juga memiliki keberhasilan terbatas dengan metode ini, seperti yang terlihat (dalam ArcMap 10.1) menyalin SDE hanya menciptakan tautan lain ke database yang sama (sedangkan jika teknik yang sama digunakan pada file atau geodatabase pribadi, salinan akan dibuat)
Krausers