1

ArcGIS 10.2.2 Standard

I'm looking for a code sample that can delete all relationship classes from a database, including inside Feature Datasets.

I've searched ESRI's site and only found a suggestion to use IDataset. I've searched google and not found anything helpful.

Do I need to delete the existing relationships prior to deleting the entire relationship class?

I got this working here is the WORKING CODE:

public Result DeleteRelationshipClasses(IWorkspace WS)
{
  try
  {
    IEnumDataset relds = WS.get_Datasets(esriDatasetType.esriDTRelationshipClass);
    IEnumDataset featds = WS.get_Datasets(esriDatasetType.esriDTFeatureDataset);
    relds.Reset();
    IDataset relclass = null;
    try
    {
      while ((relclass = relds.Next()) != null)
      {
        if (relclass.CanDelete())
          relclass.Delete();
      }
    }
    catch (Exception ex)
    {
      RecordException(ex);
    }
    featds.Reset();
    IEnumDataset classesInDs = null;
    IDataset classInDs = null;
    try
    {
      while ((relclass = featds.Next()) != null)
      {
        classesInDs = relclass.Subsets;
        classesInDs.Reset();
        while ((classInDs = classesInDs.Next()) != null)
        {
          if (classInDs.Type == esriDatasetType.esriDTRelationshipClass)
          {
            if (classInDs.CanDelete())
              classInDs.Delete();
          }
        }
      }
    }
    catch (Exception ex)
    {
      RecordException(ex);
    }
  }
  catch (Exception ex)
  {
    RecordException(ex);
    return Result.Failure(ex.Message);
  }
  return Result.Success();
}
  • 1
    Would you be able to edit your question to provide some more details about the language that you are looking for code in, where you have already looked and, preferably your code so far, please? Potential answerers are usually keener to help once they can see the effort you have gone to prior to posting a question. – PolyGeo Sep 12 '14 at 2:14
  • In general, I would avoid deleting items from an enumerator while nexting through it. Instead, I would put the datasets into a generic list, then loop through the list, deleting them. – Kirk Kuykendall Sep 18 '14 at 22:14
  • @Kirk Kuykendall, can you please elaborate on why? – GAR8 Sep 19 '14 at 4:21
1

Here's one way to do it:

public static void TestDelete()
{
    var ws = OpenFileGdb(@"\\kk1\Projects\e4\RiskCatProject.gdb");
    var d = GetDSNames(ws);

    // names don't have to reference datasets that exist, so deleting a dataset
    // a name references shouldn't cause problems.
    foreach (KeyValuePair<string, IName> kvp in d)
    {
        if (kvp.Value is IRelationshipClassName)
        {
            IDataset ds = kvp.Value.Open() as IDataset;
            Console.WriteLine("deleting {0}", ds.Name);
            ds.Delete();
        }
    }
}

public static Dictionary<string, IName> GetDSNames(IWorkspace ws)
{
    Dictionary<string, IName> dict = new Dictionary<string, IName>(StringComparer.CurrentCultureIgnoreCase);
    IEnumDatasetName enumDsname = ws.get_DatasetNames(esriDatasetType.esriDTAny);
    enumDsname.Reset();
    IDatasetName dsn;
    while ((dsn = enumDsname.Next()) != null)
    {
        dict.Add(dsn.Name,(IName) dsn);
        if (dsn is IFeatureDatasetName)
        {
            var childDict = GetChildDSNames((IFeatureDatasetName)dsn);
            foreach(KeyValuePair<string,IName> kvp in childDict)
                dict.Add(kvp.Key,kvp.Value);
        }
    }
    return dict;
}

public static Dictionary<string, IName> GetChildDSNames(IFeatureDatasetName fdsName)
{
    Dictionary<string, IName> dict = new Dictionary<string, IName>(StringComparer.CurrentCultureIgnoreCase);
    IEnumDatasetName enumDsname = ((IDatasetName)fdsName).SubsetNames;
    enumDsname.Reset();
    IDatasetName dsn;
    while ((dsn = enumDsname.Next()) != null)
    {
        if (dict.ContainsKey(dsn.Name))
        {
            string msg = string.Format("duplicate name ({0}) found in {1}/{2}",
                dsn.Name, dsn.WorkspaceName.PathName, ((IDatasetName)fdsName).Name);
            throw new Exception(msg);
        }
        dict.Add(dsn.Name, (IName)dsn);
    }
    return dict;
}

public static IWorkspace OpenFileGdb(string gdbPath)
{
    if (!Directory.Exists(gdbPath))
    {
        throw new Exception("Directory not found: " + gdbPath);
    }
    IWorkspace ws = null;
    try
    {
        Type t = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory");
        var wsf = Activator.CreateInstance(t) as IWorkspaceFactory;
        ws = wsf.OpenFromFile(gdbPath, 0);
    }
    catch (Exception ex)
    {
        throw new Exception(string.Format("Unable top open {0}", gdbPath), ex);
    }
    return ws;
}

Update In general, I don't think it's a good idea to delete elements from an enumerator. For example, C# throws an InvalidOperationException ("Collection was modified; enumeration operation may not execute") when I run this code:

List<string> l = new List<string>();
l.Add("a");
l.Add("b");
l.Add("c");
foreach (string s in l)
{
    if (s == "b")
        l.Remove(s);
}

ArcObjects doesn't throw an exception when you delete elements in a loop while you're calling IEnumWhatever.Next(), but perhaps it should.

  • Kirk, thank you for the example, I understand the process you're using. However, I'm still confused on the reason why you said " avoid deleting items from an enumerator while nexting through". Why is that a bad idea? – GAR8 Sep 24 '14 at 16:43
  • See my update. Sometimes deleting an element can confuse the implementation of the enumerator. – Kirk Kuykendall Sep 25 '14 at 13:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.