Etkin etki alanlarına sahip özellik sınıfları listeleniyor mu?


19

Tanımlanan öznitelik etki alanlarına sahip bir Esri dosyası geodatabase var . Öznitelik etki alanlarından bazılarını silmem gerekiyor, ancak "Etki alanı bir öznitelik kuralı tarafından kullanılıyor." . Hangi özellik sınıf (lar) ının etki alanlarını kullandığını nasıl öğrenebilirim?

Executing: DeleteDomain R:\v5\YT_Canvec.gdb Permanency
Start Time: Thu May 19 11:01:02 2011
ERROR 999999: Error executing function.
The domain is used by an attribute rule.
Failed to execute (DeleteDomain).
Failed at Thu May 19 11:01:02 2011 (Elapsed Time: 0.00 seconds)

Coğrafi veritabanında yüzün üzerinde özellik sınıfı vardır, etkileşimli olarak her birinin FC alan özelliklerine bakarak bir başlangıç ​​değildir. Gdb, kişisel bir gdb'ye dönüştürmek ve ms-access (yine de tehlikeli bir yöntem) ile arka kapıya gitmek için çok büyük.


(2011-Mayıs-26): Bunu ifade etmenin başka bir yolu da "hangi Özellik Sınıfı X etki alanını kullanıyor?"


Alt tür etki alanları mı kullanıyorsunuz?
Kirk Kuykendall

@kirk, evet bir alt tür var, ancak kaldırmaya çalıştığım alanlar alt türü kullanmıyor
matt wilkie

1
Bu durumda Brian'ın kodunun işe yarayacağını düşünüyorum.
Kirk Kuykendall

1
@kirk, düzeltme: Alt tipler + etki alanları kullandığımı sanmıyordum , ancak teknik destek vakası hakkında çok fazla mucking ve açtıktan sonra, aslında bir tane kullandığım ortaya çıkıyor. Kalan cuplrit'i tanımlamak gerçek bir tıklama festivaliydi. Ben c # yöntemini takip için daha fazla yatırım yapmalıydım!
matt wilkie

Yanıtlar:


3

Özellik sınıflarını alt türlerle ele alma sorusunu cevaplamak için arcpy (10.1+) ile mümkündür.

arcpy.env.workspace = your_gdb

for FC in arcpy.ListFeatureClasses():
    for stcode, stdict in list(arcpy.da.ListSubtypes(FC).items()):
        for stkey in list(stdict.keys()):
            if stkey == 'FieldValues':
                for field, fieldvals in list(stdict[stkey].items()):
                    if fieldvals[1] is not None:
                        print(
                            "{},{},{},{}".format(FC,
                                                 'None' if stcode == 0 else stdict['Name'],
                                                 field,
                                                 fieldvals[1].name))

Alt tür yoksa alt kod, stcode sıfır olacaktır, bu nedenle kod 'Yok' yazar.

Alt türler sözlüğünde daha fazlası vardır, bu yüzden kodda inceleyin.


Kabul edilen cevabımı buna değiştiriyorum. Kısa ve doğrudan. Kodunuzun sürümü github.com/envygeo/arcplus/blob/master/ArcToolbox/Scripts/… adresinde . Teşekkürler!
matt wilkie

21

Python, bir coğrafi veri tabanındaki özellik sınıflarını listeleme, listedeki her özellik sınıfında döngü oluşturma, her özellik sınıfındaki alanları listeleme ve her alanın etki alanını gösterme yöntemlerine sahiptir.

import arcpy

#Set workspace environment to geodatabase
arcpy.env.workspace = your_gdb

#Get list of feature classes in geodatabase
FCs = arcpy.ListFeatureClasses()

#Loop through feature classes in list
for FC in FCs:

    #List fields in feature class
    fields = arcpy.ListFields(FC)

    #Loop through fields
    for field in fields:

        #Check if field has domain
        if field.domain != "":

            #Print feature class, field, domain name
            print FC, field.name, field.domain

Yukarıdaki kod ArcGIS 10'da çalışmalıdır ve doğrudan python yorumlayıcı penceresinde bir liste yazdırır. Daha sonra, sonuçları daha kolay incelemek için listeyi bir metin düzenleyicisine veya Excel'e kopyalayıp yapıştırabilirsiniz.


Bu, alt türdeki alanları da ele alacak mı?
Kirk Kuykendall

Bunun alt türleri mi yoksa alt alanları mı işlediğinden emin değilim. Daha önce hiç alt tip kullanmamıştım. Belirli bir alana atanmış bir alan varsa, alan adı yazdırılır.
Brian

güzel, teşekkürler Brian. Başlangıçta benim için işe yaramadı, ama sonunda listFC'nin ekstra yardım almadan FeatureDatasets'e geri çekilmediğini hatırladım ( gis.stackexchange.com/questions/5893/… ). Şimdi her şey yolunda! :)
matt wilkie

@Kirk, hayır, alan adlarını kullanan alt türleri görmüyor.
matt wilkie

Tüm alt türleri ve bunlarla ilişkili etki alanlarını gözden geçirmek için resources.arcgis.com/en/help/main/10.1/index.html#//… örneklerini izleyin .
Michael Stimson

8

Python alt türleri işleme sanmıyorum beri, ben bu c # kodunu gönderme. Esri'nin örnek su / atık su geodb'si ile test ettim ve aşağıdaki kullanılmayan alanları buldum:

HistoryType is not used
PLSSFirstDivisionType is not used
PLSSDirection is not used
PLSSPrincipalMeridian is not used
ParcelType is not used
PLSSSpecialSurveyType is not used
CartoLineType is not used
PLSSSecondDivisionType is not used

Genellikle DBA'lar, esasen arama tabloları olan alan adlarına SQL aracılığıyla erişilemediğinden rahatsız olurlar.

Bu kod arcmap'tan test edildi ( Matt'in yorumuna göre güncellendi ):

protected override void OnClick()
{
    string fgdbPath = @"C:\projects\NetTools\InfrastructureEditingTemplate\MapsandGeodatabase\LocalGovernment.gdb";
    var dict = SummarizeDomains(fgdbPath);
    ListDomains(dict);
    // list what featureclasses use a particular domain ...
    string domName = "State_Bnd_Rules";
    if (dict.ContainsKey(domName))
    {
        if (dict[domName].Count > 0)
        {
            Debug.Print("{0} is used by these featureclasses: ", domName);
            foreach (string fcfldName in dict[domName])
            {
                Debug.Print("\t{0}", fcfldName);
            }
        }
        else
            Debug.Print("{0} is not used by any featureclasses", domName);
    }
    else
    {
        Debug.Print("Domain name not found in geodb: {0}", domName);
    }
}

private void ListDomains(Dictionary<string,List<string>> dict)
{
    foreach (KeyValuePair<string, List<string>> kvp in dict)
    {
        Debug.Print("Domain {0}",kvp.Key);
        if (kvp.Value.Count > 0)
        {
            foreach (string fcfldName in kvp.Value)
            {
                Debug.Print("\t{0}", fcfldName);
            }
        }
        else
            Debug.Print("\tUNUSED DOMAIN!");
    }
}

private Dictionary<string, List<string>> SummarizeDomains(string fgdPath)
{
    var ws = Open(fgdPath);
    var dict = InitDict(ws);

    var enumDs1 = ws.get_Datasets(esriDatasetType.esriDTAny);
    IDataset ds;
    while ((ds = enumDs1.Next()) != null)
    {
        Debug.Print("processing {0}", ds.Name);
        if (ds is IObjectClass)
            LoadDomains((IObjectClass)ds, dict);
        else if (ds is IFeatureDataset)
        {
            var enumDs2 = ds.Subsets;
            enumDs2.Reset();
            IDataset ds2;
            while ((ds2 = enumDs2.Next()) != null)
            {
                if (ds2 is IObjectClass)
                    LoadDomains((IObjectClass)ds2, dict);
            }
        }
    }
    return dict;
}
private void LoadDomains(IObjectClass oc, Dictionary<string, List<string>> dict)
{
    if (oc is ISubtypes && ((ISubtypes)oc).HasSubtype)
        LoadSubtypeDomains(oc, dict);
    else
    {
        for (int i = 0; i < oc.Fields.FieldCount; i++)
        {
            var fld = oc.Fields.get_Field(i);
            if (fld.Domain == null)
                continue;
            if (dict.ContainsKey(fld.Domain.Name))
                dict[fld.Domain.Name].Add(String.Format("{0}.{1}",((IDataset)oc).Name,fld.Name));
            else
                throw new Exception("domain not found: " + fld.Domain.Name);
        }
    }
}
private void LoadSubtypeDomains(IObjectClass oc, Dictionary<string, List<string>> dict)
{
    ISubtypes subTypes = oc as ISubtypes;
    var enumSubtypes = subTypes.Subtypes;
    enumSubtypes.Reset();
    int code;
    string stName;
    while ((stName = enumSubtypes.Next(out code)) != null)
    {
        for (int i = 0; i < oc.Fields.FieldCount; i++)
        {
            string fldName = oc.Fields.get_Field(i).Name;
            var domain = subTypes.get_Domain(code, fldName);
            if (domain != null)
            {
                if (dict.ContainsKey(domain.Name))
                    dict[domain.Name].Add(String.Format("{0}.{1}.{2}",stName,((IDataset)oc).Name,fldName));
                else
                    throw new Exception("domain not found: " + domain.Name);
            }
        }
    }
}
private Dictionary<string, List<string>> InitDict(IWorkspace ws)
{
    var dict = new Dictionary<string, List<string>>(StringComparer.InvariantCultureIgnoreCase);
    var enumDomain = ((IWorkspaceDomains)ws).Domains;
    enumDomain.Reset();
    IDomain d = null;
    while ((d = enumDomain.Next()) != null)
        dict.Add(d.Name, new List<string>());
    return dict;
}

private IWorkspace Open(string fgdbPath)
{
    Type t = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory");
    var wsf = Activator.CreateInstance(t) as IWorkspaceFactory;
    return wsf.OpenFromFile(fgdbPath, 0);
}

kullanılmayan alan adlarını listelemek yararlı olsa da, bu çözülmesi gereken sorunun tersidir. Aslında "hangi FC etki alanı X kullanıyor?" (bu yüzden bağlantıyı kaldırmak ve olabilir yapmak alan adını kullanılmayan bir alan). ((Hala kodu denemedim, sadece fonksiyonun adına gidiyorum))
matt wilkie

@matt oh, evet, bu mantıklı. Bunu nasıl yapacağınızı göstermek için kodu değiştirdim.
Kirk Kuykendall

uhh, belki bu tam teşekküllü bir soru olmalı, ama bu kodu nereye koyabilirim? VBA düzenleyicisinin v10 eşdeğerini bulamıyorum ( Araçlar-> Makrolar-> Visual Basic Düzenleyicisi ).
matt wilkie

Visual Studio Express (ücretsiz) veya daha üstünü ve ArcGIS SDK'yı kurmanız gerekir . Bunu yaptıktan sonra, bir komut düğmesi oluşturmak için bu izlenecek yolu takip edebilmeniz , ardından kodumu kopyalayıp Click etkinliğine yapıştırmanız gerekir. Ayrıca, projeye uygun referansları da eklemeniz gerekir.
Kirk Kuykendall

5

Bu kod sorulan şeyi döndürmelidir. GDB / FS çalışma alanındaki tüm özellik sınıflarını ve tablolarını başarıyla geçecek ve bir etki alanı, alan adı ve ait olduğu özellik sınıfı / tablo ile ilişkili tüm alanları döndürecektir.

import os
import arcpy
lst=[]
for dirpath,dirnames,files in arcpy.da.Walk( # the path to your workspace
, datatype=["FeatureClass","Table"]):
     for file in files:
         lst.append(os.path.join(dirpath,file))
for i in lst:
     for fld in arcpy.ListFields(i):
         if fld.domain != "":
             print os.path.basename(i),fld.name, fld.domain 

4

Maalesef Brian'ın sorulan soruya doğrudan ve kullanışlı bir cevap olan cevabı asıl sorunumu çözmüyor. Elimdeki gdb'deki bir hata nedeniyle (özellik sınıflarının hiçbirinin eklenmiş alan adları olmamasına rağmen, hala silmeme izin verilmeyen bir hata var). Her durumda, hangi fc'lerin ilişkili etki alanlarına sahip olduğunu belirlemek için başka bir yöntem buldum. Etkileşimli, ancak her fc'de her bir field özelliğini dolaşmaktan çok daha hızlı:

Sürükleyip fc demet gdb sorun başka bir gdb damla ve veri aktarımı iletişim kutusunu inceleyin . Bağlı özellik alan adları (varsa) listenin en altında bulunur. @ $% ## fc'nin zor zamanlar vermesini daraltana kadar daha küçük ve daha küçük demetlerde tekrarlayın.

sonunda bir CV alanına bağlı 2 FC'ye daraltıldı


Merakla, sürükle ve bırak HD_148009_2ifadesi CV Alanına bağlı olsa bile Permanency, Brian'ın arktik komut dosyası bağlantılı bir alan bildirmez ve ArcCatalog'daki Özellik Sınıfı Özellikleri alan denetçisi de rapor etmez. Ancak şimdi sonunda Esri teknik desteği ile bir hata raporu kaydetmek için yeterince daralttım.
matt wilkie

4

Matt Wilkie'nin arama yapmak ve Brian'ın kodunu artırmak için yazmak zorunda olduğunu hayal ediyorum. Tablolar, veritabanının kök dizinindeki özellik sınıfları ve tüm özellik veri kümelerindeki özellikler için tüm etki alanlarını almak zorunda kaldım. Bazı çalışanların eski alan adlarının coğrafi veritabanı ortamlarını temizlemelerine izin vermek için bilgileri csv olarak dışa aktardım.

def domainInfo(csvExportFolder):
    import arcpy,csv,os

    fcTabList = []
    list = []

    #Set workspace environment to geodatabase
    arcpy.env.workspace = r"H:\GIS\SDEConnections\Admin\Infrastructure.sde"

    #Prepping the csv
    csvFile = csv.writer(open(csvExportFolder+"\\"+ "Infrastructure Domains" + ".csv","wb"),delimiter = "|")
    csvFile.writerow(["FeatureDataSet","FeatureClass","FieldName","Domain"])

    #Get list of all features in geodatabase
    fdsList = arcpy.ListDatasets()
    fcs = arcpy.ListFeatureClasses()
    tbs = arcpy.ListTables()

    for fds in fdsList:
        fcs = arcpy.ListFeatureClasses("","",fds)
        if len(fcs) != 0:
            for fc in fcs:
                fcTabList.append([fds,fc])

    for fc in fcs:
        fcTabList.append([None,fc])

    for tb in tbs:
        fcTabList.append([None,tb])

    # Loop through all features in the database list
    for item in fcTabList:
        fds = item[0]
        fc = item[1]
        # List fields in feature class
        fields = arcpy.ListFields(fc)

        # Loop through fields
        for field in fields:

            # Check if field has domain
            if field.domain != "":

                # Print feature class, field, domain name
                csvFile.writerow([fds,fc,field.name,field.domain])

def main():
    csvExportFolder = r"H:\GIS"
    domainInfo(csvExportFolder)

if __name__ == "__main__":
    main()

0

Esri: SSS: Coğrafi veritabanımda alan adlarına başvuru yapılan tüm yerleri nasıl bulabilirim? . "Bu yapıların özelliklerini bir coğrafi veritabanında listeleyebilen Python işlevleri. Özellikler arasında başvurulan etki alanları vardır. Python işlevlerinin etki alanlarını ve özellik sınıflarının diğer özelliklerini listelemek için nasıl kullanılabileceğini gösteren örnek bir komut dosyası ve dosya coğrafi veritabanı sağlanmıştır. Alanlar bir özellik sınıfındaki veya tablodaki alanlarla ilişkilendirilebilir; ayrıca bir alt türle kategorilere ayrılan alanlar için de ayarlanabilir. "

Sonuçlar, bu alan için kullanılan alanların ötesine geçerek gürültülüdür, ancak başlamak için daha geniş bir platformdur.

Executing: ParseDomainReferences [...]

fc at root level: Pt1
  fld OBJECTID
  fld SHAPE
  fld Field_Text, domain [Pets]
  fld Field_Long
  fld Field_Short, domain [Counts]
  fld Field_Double, domain [Ratios]
[...]
Subtype Code: 1
subCode: ('Default', False)
subCode: ('Name', u'One')
subCode: ('SubtypeField', u'Field_Long')
FieldValues
fldName: Field_Double, default: [no default], domain: Ratios
fldName: OBJECTID, default: [no default], domain: [no domain]
fldName: Field_Long, default: [no default], domain: [no domain]
fldName: Field_Short, default: 1, domain: Counts
fldName: SHAPE, default: [no default], domain: [no domain]
fldName: Field_Text, default: N, domain: [no domain]
[...etc]

Kısalık için düzenlenmiş kod alıntısı:

def ParseFieldList (fc, fcPath):
...
      for fld in fldList:
        if fld.domain != None:
          if fld.domain != "":
...
        arcpy.AddMessage ("  fld " + fld.name + s)

      # get subtype list
      subDict = arcpy.da.ListSubtypes (fcPath)
      if len (subDict) > 0:
        for stCode in subDict.iteritems():
...
          valkey, vallist = stCode
          arcpy.AddMessage ("Subtype Code: {0}".format(valkey))
          i = 0
          for subCode in vallist.iteritems():
            i += 1
            if i < 4:
              arcpy.AddMessage ("subCode: {0}".format(subCode))
            else:
              fldkey, fldlist = subCode
              arcpy.AddMessage (fldkey)
              for fld in fldlist.iteritems():
...
                if dom != None:
                  s2 = dom.name
                arcpy.AddMessage ("fldName: " + fldName + ", default: " + s1 + ", domain: " + s2)
...
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.