Connect to Geodatabase Featureclass and/or shapefile

3069
16
Jump to solution
02-10-2013 06:17 PM
GinoMellino
Occasional Contributor
Hi All,

This is probably very simple. I can load a geodatabase featureclass with IWorkspace::OpenFromFile and the FileGDBWorkspaceFactory CoClass and likewise with ShapefileWorkspaceFactoryClass for shapefiles...is there a way to load both with the same generic workspace factory or do I have to set a different one based on what is selected in my custom Add data dialog?

Thanks in advance
Gino
0 Kudos
1 Solution

Accepted Solutions
AlexanderGray
Occasional Contributor III
The interface is generic (IWorkspaceFactory) but the classes that implement it are all specific to the data type.  There isn't a workspaceFactory Factory class that creates the one you need based on the data type you input or that figures out the data type provided in the file path (.shp, .gdb or .sde.)  To make it would be easy but of limited value.

View solution in original post

0 Kudos
16 Replies
LeoDonahue
Occasional Contributor III

This is probably very simple. I can load a geodatabase featureclass with IWorkspace::OpenFromFile and the FileGDBWorkspaceFactory CoClass and likewise with ShapefileWorkspaceFactoryClass for shapefiles...is there a way to load both with the same generic workspace factory or do I have to set a different one based on what is selected in my custom Add data dialog?


There is a generic workspace factory, it's called IWorkspaceFactory.  Many other concrete classes implement this Interface, such as the two types you mentioned.
0 Kudos
AlexanderGray
Occasional Contributor III
The interface is generic (IWorkspaceFactory) but the classes that implement it are all specific to the data type.  There isn't a workspaceFactory Factory class that creates the one you need based on the data type you input or that figures out the data type provided in the file path (.shp, .gdb or .sde.)  To make it would be easy but of limited value.
0 Kudos
LeoDonahue
Occasional Contributor III
The interface is generic (IWorkspaceFactory) but the classes that implement it are all specific to the data type.

You are correct sir.

I was being intentionally less obvious to the OP because I thought maybe they would see the difference between Interfaces and Classes and realize the answer to their question.
0 Kudos
AlexanderGray
Occasional Contributor III
You are correct sir.

I was being intentionally less obvious to the OP because I thought maybe they would see the difference between Interfaces and Classes and realize the answer to their question.


I didn't mean your answer was incorrect or anything.  I just got thinking about the class factory design pattern, in which the factory class decides what type of object to create.  This is different from the workspace factory since you have to know what type of workspace you want (shapefile, file gdb, sde, etc.) before creating a specific type of workspace factory to get that same type of workspace.  It strikes me as somewhat going against what the factory design pattern is supposed to be.  Factories are supposed to decide the specific class type for you...
0 Kudos
GinoMellino
Occasional Contributor
Hi all and thanks for the replies.

I did recognise that IWorkspaceFactory was an interface but must apologise as I lack a good understanding of programming. I thought that there may be a generic coclass which implements IWorkspaceFactory which I could use. Thanks Alexander for clearing this up.

I am trying to use a GXDialog to add data of any kind to a map, which is why I need to be able to handle the user selecting Shapefile/GDB/SDE data sources. Is there a recommended way of handling these different types of data? Currently as a work around I test for the .shp extension to determine if its type.

Again, Thanks for your help
0 Kudos
LeoDonahue
Occasional Contributor III
There is a really cool thing called the ArcObjects API.  Granted, I can't hold it against anyone who tries to make sense of the ArcObjects .NET API, because you can't find anything without expanding, expanding, expanding..

This is a Java example, so sorry for that.

I opened eclipse and used the new project wizard to create a console application.  Then I used the sample ArcGIS snippets for listing feature classes of a FGDB workspace.

Notice in listFeatureclass, they use the concrete class FileGeodatabaseWorkspaceFactory to create new FileGeodatabaseWorkspaceFactory.

Notice in listFeatureclass2, we're using the WorkspaceFactory class  .. what?  What kind of black magic is that?

Give them a try, pass in a file name of "c:\\myfgdb.gdb" and see what happens.

    public static void listFeatureclass(String file) throws java.net.UnknownHostException, java.io.IOException {
        com.esri.arcgis.datasourcesGDB.FileGDBWorkspaceFactory factory = new com.esri.arcgis.datasourcesGDB.FileGDBWorkspaceFactory();
        com.esri.arcgis.geodatabase.IWorkspace workspace = factory.openFromFile(file, 0);
        com.esri.arcgis.geodatabase.IEnumDataset enumDataset = workspace.getDatasets(com.esri.arcgis.geodatabase.esriDatasetType.esriDTFeatureClass);
        com.esri.arcgis.geodatabase.IDataset ds = null;    
        ds = enumDataset.next();
        while(ds != null){
            com.esri.arcgis.geodatabase.IFeatureClass fClass = new com.esri.arcgis.geodatabase.IFeatureClassProxy(ds);
            int fCount = fClass.featureCount(null);
            System.out.println("FeatureClass "+ fClass.getAliasName() +" has "+fCount+ " features.");
            ds = enumDataset.next();
        }
    }
    
    public static void listFeatureclass2(String file) throws java.net.UnknownHostException, java.io.IOException {
        com.esri.arcgis.geodatabase.WorkspaceFactory factory = new com.esri.arcgis.geodatabase.WorkspaceFactory(new com.esri.arcgis.datasourcesGDB.FileGDBWorkspaceFactory());
        com.esri.arcgis.geodatabase.IWorkspace workspace = factory.openFromFile(file, 0);
        com.esri.arcgis.geodatabase.IEnumDataset enumDataset = workspace.getDatasets(com.esri.arcgis.geodatabase.esriDatasetType.esriDTFeatureClass);
        com.esri.arcgis.geodatabase.IDataset ds = null;    
        ds = enumDataset.next();
        while(ds != null){
            com.esri.arcgis.geodatabase.IFeatureClass fClass = new com.esri.arcgis.geodatabase.IFeatureClassProxy(ds);
            int fCount = fClass.featureCount(null);
            System.out.println("FeatureClass "+ fClass.getAliasName() +" has "+fCount+ " features.");
            ds = enumDataset.next();
        }
    }
0 Kudos
LeoDonahue
Occasional Contributor III
I just got thinking about the class factory design pattern, in which the factory class decides what type of object to create.  This is different from the workspace factory since you have to know what type of workspace you want (shapefile, file gdb, sde, etc.) before creating a specific type of workspace factory to get that same type of workspace.  It strikes me as somewhat going against what the factory design pattern is supposed to be.  Factories are supposed to decide the specific class type for you...


Are you talking about the Factory Method pattern?  If yes, then you create an interface for creating objects, and let subclasses define what type of object is being created.

You could do something lame like this, but don't.

com.esri.arcgis.datasourcesfile.ShapefileWorkspaceFactory shp = new com.esri.arcgis.datasourcesfile.ShapefileWorkspaceFactory();

com.esri.arcgis.datasourcesGDB.FileGDBWorkspaceFactory fgdb = new com.esri.arcgis.datasourcesGDB.FileGDBWorkspaceFactory();

           
            createWorkspace("d:\\somefolder",shp,"someshapefilename");
            createWorkspace("d:\\somefolder\\somegeodatabase.gdb",fgdb,null);

    public static void createWorkspace(String filePath, IWorkspaceFactory temp, String shapefileName){
        
        try {
            if(temp.getWorkspaceType() == esriWorkspaceType.esriFileSystemWorkspace){
                com.esri.arcgis.geodatabase.WorkspaceFactory wsf = new com.esri.arcgis.geodatabase.WorkspaceFactory(temp);
                com.esri.arcgis.geodatabase.Workspace work = new com.esri.arcgis.geodatabase.Workspace(wsf.openFromFile(filePath, 0));
                com.esri.arcgis.geodatabase.IFeatureClass featureClass = work.openFeatureClass(shapefileName);
                System.out.println(featureClass.getAliasName() + " " + featureClass.featureCount(null));
            }
            
            if(temp.getWorkspaceType() == esriWorkspaceType.esriLocalDatabaseWorkspace){
                com.esri.arcgis.geodatabase.WorkspaceFactory factory = new com.esri.arcgis.geodatabase.WorkspaceFactory(temp);
                com.esri.arcgis.geodatabase.IWorkspace workspace = factory.openFromFile(filePath, 0);
                com.esri.arcgis.geodatabase.IEnumDataset enumDataset = workspace.getDatasets(com.esri.arcgis.geodatabase.esriDatasetType.esriDTFeatureClass);
                com.esri.arcgis.geodatabase.IDataset ds = null;    
                ds = enumDataset.next();
                while(ds != null){
                    com.esri.arcgis.geodatabase.IFeatureClass fClass = new com.esri.arcgis.geodatabase.IFeatureClassProxy(ds);
                    int fCount = fClass.featureCount(null);
                    System.out.println(fClass.getAliasName() +" has "+fCount+ " features.");
                    ds = enumDataset.next();
                }
            }
        } catch (AutomationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }
0 Kudos
AlexanderGray
Occasional Contributor III
Are you talking about the Factory Method pattern?  If yes, then you create an interface for creating objects, and let subclasses define what type of object is being created.


Yes I was talking about Factory method pattern.  I was thinking something along those lines.  A class where you just pass a string in the constructor, no workspace factory, and it spit out the appropriate workspace. It seems like a recipe for trouble for not much gain.  I really don't feel like maintaining the code for every possible type of workspace including some that don't exist yet. Now if that sort of class was provided as part of the API, like an actual factory class, it would abstract a lot of the things you need to do and would reduce programmer error.

WorkspaceFactory Class
  ctor workspaceStr
    Determine type of workspace needed
    Create workspace factory for type

  workspace property
    Open workspace
    return workspace
0 Kudos
AlexanderGray
Occasional Contributor III
There is a really cool thing called the ArcObjects API.  Granted, I can't hold it against anyone who tries to make sense of the ArcObjects .NET API, because you can't find anything without expanding, expanding, expanding..

This is a Java example, so sorry for that.

I opened eclipse and used the new project wizard to create a console application.  Then I used the sample ArcGIS snippets for listing feature classes of a FGDB workspace.

Notice in listFeatureclass, they use the concrete class FileGeodatabaseWorkspaceFactory to create new FileGeodatabaseWorkspaceFactory.

Notice in listFeatureclass2, we're using the WorkspaceFactory class  .. what?  What kind of black magic is that?

Give them a try, pass in a file name of "c:\\myfgdb.gdb" and see what happens.

    public static void listFeatureclass(String file) throws java.net.UnknownHostException, java.io.IOException {
        com.esri.arcgis.datasourcesGDB.FileGDBWorkspaceFactory factory = new com.esri.arcgis.datasourcesGDB.FileGDBWorkspaceFactory();
        com.esri.arcgis.geodatabase.IWorkspace workspace = factory.openFromFile(file, 0);
        com.esri.arcgis.geodatabase.IEnumDataset enumDataset = workspace.getDatasets(com.esri.arcgis.geodatabase.esriDatasetType.esriDTFeatureClass);
        com.esri.arcgis.geodatabase.IDataset ds = null;    
        ds = enumDataset.next();
        while(ds != null){
            com.esri.arcgis.geodatabase.IFeatureClass fClass = new com.esri.arcgis.geodatabase.IFeatureClassProxy(ds);
            int fCount = fClass.featureCount(null);
            System.out.println("FeatureClass "+ fClass.getAliasName() +" has "+fCount+ " features.");
            ds = enumDataset.next();
        }
    }
    
    public static void listFeatureclass2(String file) throws java.net.UnknownHostException, java.io.IOException {
        com.esri.arcgis.geodatabase.WorkspaceFactory factory = new com.esri.arcgis.geodatabase.WorkspaceFactory(new com.esri.arcgis.datasourcesGDB.FileGDBWorkspaceFactory());
        com.esri.arcgis.geodatabase.IWorkspace workspace = factory.openFromFile(file, 0);
        com.esri.arcgis.geodatabase.IEnumDataset enumDataset = workspace.getDatasets(com.esri.arcgis.geodatabase.esriDatasetType.esriDTFeatureClass);
        com.esri.arcgis.geodatabase.IDataset ds = null;    
        ds = enumDataset.next();
        while(ds != null){
            com.esri.arcgis.geodatabase.IFeatureClass fClass = new com.esri.arcgis.geodatabase.IFeatureClassProxy(ds);
            int fCount = fClass.featureCount(null);
            System.out.println("FeatureClass "+ fClass.getAliasName() +" has "+fCount+ " features.");
            ds = enumDataset.next();
        }
    }



That is really interesting, Java is very different when it comes to that sort of thing.  You can't do that in .NET, the constructor for workspacefactory is not accessible outside the its own assembly.   Typically in .NET you don't declare an object as a class, always an interface
even if you know the exact type of class to which you have a reference, the .NET runtime still does not have the required metadata to cast the variable to a strongly typed RCW

http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#//000100000151000000
0 Kudos