ArcEngine打开本地数据库

Posted wgj-blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ArcEngine打开本地数据库相关的知识,希望对你有一定的参考价值。

先看一下GeoDatabase核心结构模型图:

   技术图片

1  工作空间工厂WorkspaceFactory对象

   WorkspaceFactory是GeoDatabase的入口,是一个抽象类,拥有很多子类,例如SdeWorkspaceFactory, AccessWorkspaceFactory, ShapfileWorkspaceFactory  CadWorkspaceFactory等

   IWorkspaceFactory接口定义了所有工作空间对象的一般属性和方法

   public IWorkspaceName Create (string parentDirectory,string Name,IPropertySet ConnectionProperties,int hWnd);用于产生一个新的工作空间名称对象,前两个参数是数据库的路径和名称,第三个参数是一个属性集(properset)对象。
   public IWorkspace Open ( IPropertySet ConnectionProperties,int hWnd);打开一个已经存在的工作空间像SDE数据库等;

      public IWorkspace OpenFromFile (string fileName,int hWnd);打开一个文件类型的数据

2 工作空间WorkSpace对象

   Workspace在逻辑上是一个包含空间数据集和非空间数据集的数据容器,数据包括要素类、栅格数据集、表等对象

   Workspace对象主要的一些接口:

        1 IWorkspace接口:定义了一个工作空间最普通的属性和方法。

        2  IFeatureWorkspace接口

        这个接口主要用于管理要素的数据集,如表(Table)、对象类(ObjectClass)、要素类(FeatureClass)、要素数据集(FeatureDataset)和关系类(RelationshipClass)等。

   主要的成员:

  技术图片

   public IFeatureClass OpenFeatureClass ( string Name) 打开一个已经存在的要素类,无论这个要素类是在工作空间还是在一个要素数据集中
    public IFeatureDataset OpenFeatureDataset (string Name);打开一个已经存在的要素数据集
    public ITable OpenTable (string Name);打开一个已经存在的表; 

3 RasterWorkspace对象

   主要实现了IRasterWorkspace接口

    public IRasterDataset OpenRasterDataset ( string Name);

4 属性集Propertyset对象

  Propertyset对象是一个专门用于设置属性的对象,它是一种name-value对应的集合,类似于Hash表。属性名必须是字符串,属性值可以是字符串、数值或日期也可以是一个对象

  public void SetProperty (string Name, object Value);

5 DataSet数据集对象

   Dataset对象可分为两大类:Table和GeoDataset,GeoDataset是一个抽象类,代表了拥有空间属性的数据集,包括FeatureDataset、要素类FeatureClass、TIN和栅格数据集RasterDataset。

6  FeatureDataset对象

 实现的主要接口:

1 IFeatureDataset接口

      public IEnumDataset Subsets {get;}Datasets contained within this dataset.

2 IFeatureClassContainer接口

   用于管理要素数据集里面的要素类,该接口的ClassByName和Class(index)等属性可以用来获取数据集中的特定的要素类(这里很奇怪在帮助文档中只有属性没有方法但点进去却是一个方法Ok你大概不理解我说的)

       public IFeatureClass get_Class (int ClassIndex);

       public IFeatureClass get_ClassByID (int ID);

      public IFeatureClass get_ClassByName (string Name);

   接下来举几个加载各种数据的例子

   1 加载Shapefiles文件

            OpenFileDialog dlg=new OpenFileDialog();
            dlg.Title="打开shapefile文件";
            dlg.Filter="(*.shp)|*.shp";
            dlg.ShowDialog();
            string filename=dlg.FileName;
            int index=filename.LastIndexOf(@"");
            string path=filename.Substring(0,index);
            string name=filename.Substring(index+1);

            IWorkspaceFactory pWsFactory = new ShapefileWorkspaceFactoryClass();
            IFeatureWorkspace  pWorkSpace = pWsFactory.OpenFromFile(path, 0) as IFeatureWorkspace;
            IFeatureClass pFeatureClass = pWorkSpace.OpenFeatureClass(name);
            IFeatureLayer pFeatureLayer = new FeatureLayerClass();
            pFeatureLayer.Name = pFeatureClass.AliasName;
            pFeatureLayer.FeatureClass = pFeatureClass;

            axMapControl1.Map.AddLayer(pFeatureLayer);
            axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);

   2.加载栅格数据

            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Title = "打开Raster文件";
            dlg.Filter = " Layer File(*.lyr)|*.jpg;*.bmp;*.tiff ";
            dlg.ShowDialog();
            string filename = dlg.FileName;
            int index = filename.LastIndexOf(@"");
            string path = filename.Substring(0, index);
            string name = filename.Substring(index + 1);

            IWorkspaceFactory pWsFactory =new RasterWorkspaceFactoryClass();
            IRasterWorkspace pRasterWorkspace = pWsFactory.OpenFromFile(path, 0) as IRasterWorkspace;
            IRasterDataset pRasterDataset = pRasterWorkspace.OpenRasterDataset(name);
            IRasterLayer pRasterLayer = new RasterLayerClass();
            pRasterLayer.CreateFromDataset(pRasterDataset);
            axMapControl1.Map.AddLayer(pRasterLayer);
            axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);

    3 加载CAD数据

            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Title = "打开CAD文件";
            dlg.Filter = " CAD(*.dwg)|*.dwg|All Files(*.*)|*.* ";
            dlg.ShowDialog();
            string filename = dlg.FileName;
            int index = filename.LastIndexOf(@"");
            string path = filename.Substring(0, index);
            string name = filename.Substring(index + 1);

            IWorkspaceFactory pWsFactory = new CadWorkspaceFactoryClass();
            IFeatureWorkspace pFeatureWorkspace = pWsFactory.OpenFromFile(path, 0) as IFeatureWorkspace;
            IFeatureDataset pFeatureDataset = pFeatureWorkspace.OpenFeatureDataset(name);
            IFeatureClassContainer pFCContainer = pFeatureDataset as IFeatureClassContainer;
            for (int i = 0; i < pFCContainer.ClassCount; i++)
            {
                IFeatureClass pFeatureClass = pFCContainer.get_Class(i);
                if (pFeatureClass.FeatureType == esriFeatureType.esriFTCoverageAnnotation)
                {
                    IFeatureLayer pFeatureLayer = new CadAnnotationLayerClass();

                }
                else
                {
                    IFeatureLayer pFeatureLayer = new FeatureLayerClass();
                    pFeatureLayer.FeatureClass = pFeatureClass;
                    pFeatureLayer.Name = pFeatureClass.AliasName;
                    axMapControl1.Map.AddLayer(pFeatureLayer);

                }
                axMapControl1.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);

      4 加载PersonGeodatabase数据

        

            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Title = "打开Geodatabase文件";
            dlg.Filter = " Personal Geodatabase(*.mdb)|*.mdb|All Files(*.*)|*.* ";
            dlg.ShowDialog();
            string path = dlg.FileName;
          

            IWorkspaceFactory pAccessWorkspaceFactory;
            IFeatureWorkspace pFeatureWorkspace;
            IFeatureLayer pFeatureLayer;
            IFeatureDataset pFeatureDataset;
            pAccessWorkspaceFactory = new AccessWorkspaceFactoryClass();
          
            IWorkspace pWorkspace = pAccessWorkspaceFactory.OpenFromFile(path, 0);
            IEnumDataset pEnumDataset = pWorkspace.get_Datasets(ESRI.ArcGIS.Geodatabase.esriDatasetType.esriDTAny);
            pEnumDataset.Reset();
            IDataset pDataset = pEnumDataset.Next();
           
            if (pDataset is IFeatureDataset)
            {
                pFeatureWorkspace = (IFeatureWorkspace)pAccessWorkspaceFactory.OpenFromFile(path, 0);
                pFeatureDataset = pFeatureWorkspace.OpenFeatureDataset(pDataset.Name);
                IEnumDataset pEnumDataset1 = pFeatureDataset.Subsets;
                pEnumDataset1.Reset();
                IDataset pDataset1 = pEnumDataset1.Next();
               
                if (pDataset1 is IFeatureClass)
                {
                    pFeatureLayer = new FeatureLayerClass();
                    pFeatureLayer.FeatureClass = pFeatureWorkspace.OpenFeatureClass(pDataset1.Name);
                    pFeatureLayer.Name = pFeatureLayer.FeatureClass.AliasName;
                    axMapControl1.Map.AddLayer(pFeatureLayer);
                    axMapControl1.ActiveView.Refresh();
                }
              
             
            }
            else
            {
                pFeatureWorkspace = (IFeatureWorkspace)pWorkspace;
                pFeatureLayer = new FeatureLayerClass();
                pFeatureLayer.FeatureClass = pFeatureWorkspace.OpenFeatureClass(pDataset.Name);
                pFeatureLayer.Name = pFeatureLayer.FeatureClass.AliasName;
                axMapControl1.Map.AddLayer(pFeatureLayer);
                axMapControl1.ActiveView.Refresh();
            }

 

1、加载个人数据库
个人数据库是保存在Access中的数据库。其加载方式有两种:通过名字和通过属性加载(也许不只这两种,AE中实现同一功能可以有多种方式)。
A、通过设置属性加载个人数据库。
首先通过IPropertySet接口定义要连接数据库的一些相关属性,在个人数据库中为数据库的路径,例如:
IPropertySet  Propset = new PropertySetClass(); 
           Propset.SetProperty("DATABASE",@"D: estAodatashMapData.mdb" );
      当定义完属性并设置属性后就可以进行打开数据库的操作了,在ArcEngine开发中存在IWorkspaceFactory、 IFeatureWorkspace、IFeatureClass、IFeatureLayer等几个常用的用于打开和操作数据空间地物的接口。 IWorkspaceFactory是一个用于创建和打开工作空间的接口,它是一个抽象的接口,我们在具体应用时要用对应的工作空间实例化它,如下:
IWorkspaceFactory Fact = new AccessWorkspaceFactoryClass ();
如果我们打开的是SDE数据库就要用SdeWorkspaceFactoryClass实例化Fact。当我们完成了工作空间的实例化后就可以根据上边设置的属性打开对应的Access数据库了。打开方式如下:
         IFeatureWorkspace Workspace = Fact.Open(Propset,0) as IFeatureWorkspace;
打开Access工作空间后接下来的事情是做什么了,很简单,找到对应的地物类,赋给相应的层,通过MapControl控件添加对应的层,然后刷新地图。以下为添加某一层的代码:
       IFeatureClass Fcls = Workspace.OpenFeatureClass("District");
       IFeatureLayer Fly = new FeatureLayerClass();
       Fly.FeatureClass = Fcls;
       MapCtr.Map.AddLayer (Fly);
       MapCtr.ActiveView.Refresh();
其中District为地物类的名字,MapCtr为AE中MapControl的对象。上边的通过属性设置加载数据空间的方式还可以用于SDE 数据库,在SDE数据库加载时会介绍。
以下为通过设置属性加载Access数据库的完整C#代码:
public void AddAccessDBByPro()
{
       IPropertySet  Propset = new PropertySetClass(); 
       Propset.SetProperty("DATABASE",@"D: estAodatashMapData.mdb" );
       IWorkspaceFactory Fact = new AccessWorkspaceFactoryClass ();
       IFeatureWorkspace Workspace = Fact.Open(Propset,0) as IFeatureWorkspace;
         
       IFeatureClass Fcls = Workspace.OpenFeatureClass ("District");
       IFeatureLayer Fly = new FeatureLayerClass();
       Fly.FeatureClass = Fcls;
 
       MapCtr.Map.AddLayer(Fly);
       MapCtr.ActiveView.Refresh();
}
B、通过数据库名字加载个人数据库
在这我先把完整的代码写出来,让您先跟上边的代码做个对比。以下为完整的代码:
public void AddAccessDBByName()
{
      IWorkspaceName  pWorkspaceName = new WorkspaceNameClass() ;
    pWorkspaceName.WorkspaceFactoryProgID = "esriDataSourcesGDB.AccessWorkspaceFactory";
      pWorkspaceName.PathName = @"D: estAodatashMapData.mdb";
      IName n = pWorkspaceName as IName ;
      IFeatureWorkspace Workspace = n.Open() as IFeatureWorkspace;
                                                             
     IFeatureClass Fcls = Workspace.OpenFeatureClass ("District");
     IFeatureLayer Fly = new FeatureLayerClass();
     Fly.FeatureClass = Fcls;
     MapCtr.Map.AddLayer (Fly);
     MapCtr.ActiveView.Refresh();
}
细心的人已经注意到,打开Access工作空间后接下来的代码是一样的,都是找到对应的地物类,赋给相应的层,通过MapControl控件添加 对应的层,然后刷新地图。现在讲解一下上边的代码,首先是创建一个个人数据库工作空间名,在指定工作空间名的ProgID,以确定打开的是什么类型的工作 空间,例如在打开Access个人数据库时使用的是下边的代码:
  IWorkspaceName  pWorkspaceName = new WorkspaceNameClass() ;
pWorkspaceName.WorkspaceFactoryProgID = "esriDataSourcesGDB.AccessWorkspaceFactory";
pWorkspaceName.PathName = @"D: estAodatashMapData.mdb";
属性WorkspaceFactoryProgID可以确保工作空间是AccessWorkspaceFactory,即个人数据库,同时指定要 打开数据库的路径。为了打开数据库,我们通过AE的类图可以发现打开工作空间必须使用IName接口(个人认为,不一定正确,可以思考一下看有其他办法没 有),所以接着定义IName对象,并把工作空间名转换成IName类型并赋值给IName对象,然后通过IName对象的Open()方法打开相应的工 作空间,代码如下:
IName n = pWorkspaceName as IName ;
IFeatureWorkspace Workspace = n.Open () as IFeatureWorkspace;
接下来的事情就是上边提到。
2、加载SDE数据库
什么是SDE数据库?这个问题要详细地讲解将花费大量的时间,但我可以告诉你SDE空间数据库可以是任何关系数据库。ESRI公司为了使空间数据 能保存在关系数据库中,并且能很好的查询相关的空间属性而开发的一个中间件,使用SDE能很好的将空间数据保存在关系数据库中。如Orcale, SQL Server 等。SDE具体细节的了解请查找相关的资料,这里只介绍怎么连接SDE数据库。SDE数据库的联机分为直接连接和通过SDE连接。当服务器的性能比较好的 时候可以采用SDE连接,否则采用直接连接,这样可以减轻服务器的任务。建议采用直接连接,其实,SDE连接方式和直接连接的方式只是一个属性参数设置的 问题。跟个人数据库采用属性连接的方式一样,先定义一个属性对象,然后设置属性参数,接着定义一个工作空间并用 SdeWorkspaceFactoryClass()实例化它,接着加在加载图层,至于加载图层的代码,与加载个人数据库中图层的方法一样,其实不只加 载这两种数据类型,加载其他类型的数据时也是采用相同的方法加载图层,只是工作空间采用不同的实例而已,下边为完整的对吗”//”后的为注析:
public void AddSDELayer(bool ChkSdeLinkModle)
{
     //定义一个属性
     IPropertySet  Propset = new PropertySetClass(); 
     if (ChkSdeLinkModle==true) // 采用SDE连接
     { 
            //设置数据库服务器名,服务器所在的IP地址
           Propset.SetProperty ("SERVER", "192.168.2.41");
            //设置SDE的端口,这是安装时指定的,默认安装时"port:5151"
           Propset.SetProperty ("INSTANCE", "port:5151");
            //SDE的用户名
           Propset.SetProperty ("USER", "sa");
            //密码
           Propset.SetProperty ("PASSWORD", "sa");
          //设置数据库的名字,只有SQL Server  Informix 数据库才需要设置
           Propset.SetProperty ("DATABASE", "sde");
           //SDE的版本,在这为默认版本
           Propset.SetProperty ("VERSION", "SDE.DEFAULT");
     }
     else // 直接连接
     {
           //设置数据库服务器名,如果是本机可以用"sde:sqlserver:."
           Propset.SetProperty ("INSTANCE", "sde:sqlserver:zhpzh");
            //SDE的用户名
           Propset.SetProperty ("USER", "sa");
            //密码
           Propset.SetProperty ("PASSWORD", "sa");
          //设置数据库的名字,只有SQL Server  Informix 数据库才需要设置           
          Propset.SetProperty ("DATABASE", "sde");
          //SDE的版本,在这为默认版本
          Propset.SetProperty ("VERSION", "SDE.DEFAULT");
    }
    //定义一个工作空间,并实例化为SDE的工作空间
    IWorkspaceFactory Fact = new SdeWorkspaceFactoryClass();
    //打开SDE工作空间,并转化为地物工作空间
    IFeatureWorkspace Workspace = (IFeatureWorkspace )Fact.Open(Propset,0);
    /*定义一个地物类,并打开SDE中的管点地物类,写的时候一定要写全.如SDE中有一个管点层,你不能写成IFeatureClass Fcls = Workspace.OpenFeatureClass ("管点");这样,一定要写成下边的样子.*/
       IFeatureClass Fcls = Workspace.OpenFeatureClass ("sde.dbo.管点");
           
       IFeatureLayer Fly = new FeatureLayerClass ();
       Fly.FeatureClass = Fcls;
       MapCtr.Map.AddLayer (Fly);
       MapCtr.ActiveView.Refresh ();
    }
不知道注意到了没有,直接连接跟SDE连接的最大的不同是直接连接不要设置端口,同时他们的参数设置也不一样,好好注意参数的设置。

3、加载CAD图层
CAD图层的加载可以分为:分图层加载和整幅图加载
A、分图层加载
我们可以把CAD图分为点、线、面、标注加载到MapControl中,跟加载其他数据一样,首先要定义一个工作空间,并用 CadWorkspaceFactoryClass()实例化它,当得到了工作空间后就可以打开相应的工作空间,然后再打开指定的层类型。下边为完整的代 码:
 public void AddCADByLayer()
    {
      //定义工作空间,并用CadWorkspaceFactoryClass()实例化它
   IWorkspaceFactory Fact = new CadWorkspaceFactoryClass();
   //打开相应的工作空间,并赋值给要素空间,OpenFromFile()
   //中的参数为CAD文件夹的路径
IFeatureWorkspace Workspace = Fact.OpenFromFile(@"I: est",0)  as IFeatureWorkspace;      
       /*打开线要素类,如果要打开点类型的要素,需要把下边的代码该成:
   IFeatureClass Fcls = Workspace.OpenFeatureClass ("modle.dwg:point");
由此可见modle.dwg为CAD图的名字,后边加上要打开的要素类的类型,中间用冒号隔开,大家可以想想多边形和标注是怎么打开的。 */
     IFeatureClass Fcls = Workspace.OpenFeatureClass ("modle.dwg:polyline");            
       IFeatureLayer Fly = new FeatureLayerClass ();
       Fly.FeatureClass = Fcls;
MapCtr.Map.AddLayer (Fly);
       MapCtr.ActiveView.Refresh ();
}
B、整幅CAD图的加载
当我们要加载整幅CAD图时,需要使用下边的代码,这跟加载地物类有一定的区别,详细地介绍请看代码中的注析:
public void AddWholeCAD()
{
       /*下边的两行代码是定义一个CAD工作空间,然后打开它,但这次不是赋值给
    IFeatureWorkspace对象,而是赋值给IWorkspace定义的对象*/
IWorkspaceFactory Fact = new CadWorkspaceFactoryClass();
       IWorkspace Workspace = Fact.OpenFromFile(@"I: est",0);     
  //定义一个CAD画图空间,并把上边打开的工作空间赋给它
       ICadDrawingWorkspace dw =  Workspace as ICadDrawingWorkspace;
  //定义一个CAD的画图数据集,并且打开上边指定的工作空间中一幅CAD图
  //然后赋值给CAD数据集
       ICadDrawingDataset ds = dw.OpenCadDrawingDataset ("modle.DWG");
  //通过ICadLayer类,把上边得到的CAD数据局赋值给ICadLayer类对象的
  //CadDrawingDataset属性
       ICadLayer CadLayer = new  CadLayerClass();
       CadLayer.CadDrawingDataset = ds;
        //利用MapControl加载CAD层
       MapCtr.Map.AddLayer (CadLayer);
     MapCtr.ActiveView.Refresh ();
}

复制的这个https://www.cnblogs.com/henyihanwobushi/archive/2013/03/20/2971271.html

以上是关于ArcEngine打开本地数据库的主要内容,如果未能解决你的问题,请参考以下文章

C#+ArcEngine中com对象的释放问题

根据图片的url地址下载图片到本地保存代码片段

ArcEngine10.0三维开发

在ArcEngine中如何读取tin的数据,需要读所有三角网的点号、坐标?

ArcEngine 添加多个要素为啥不能同时显示

微信小程序代码片段