gis
gis
管理员
管理员
  • 注册日期2003-07-16
  • 发帖数15945
  • QQ554730525
  • 铜币25337枚
  • 威望15352点
  • 贡献值0点
  • 银元0个
  • GIS帝国居民
  • 帝国沙发管家
  • GIS帝国明星
  • GIS帝国铁杆
阅读:2980回复:1

SQL Server 2008空间数据库 应用程序开发演练

楼主#
更多 发布于:2009-06-11 13:33
<P>卢世松 </P>
<P>(云南省测绘工程院  650033) </P>
<P><BR>     摘要 :SQL Server 2008在空间数据支持上提供了许多强大的功能,使用其提供的空间数据类型对象,利用强大的开发工具Visual Studio开发工具基于.NET平台 ,使用 现代的面向对象编程语言C#可快速的开发出操控空间数据的应用程序。本文通过使用C#开发一个基于SQL Server2008创建、操控空间数据的GDI+图形应用程序,介绍SQL Server 2008空间数据库应用程序的开发 。 </P>
<P>    关键词:空间数据库;SQL Server; C#; GIS ;GDI+。 </P>
<P><BR>1.  引言 </P>
<P>地理信息系统(GIS)具有强大的地图制图、空间分析功能,其目的是提供一个空间框架,以支持地球资源的合理利用决策和管理人工环境。随着数据库技术的发展,对于海量空间数据的存储和管理,都已经交由数据库系统来完成。 由于空间数据具有空间位置、非结构化、空间关系、分类编码、海量数据等特征,一般的 关系 数据库管理系统难以满足要求。 为满足空间海量数据存储、管理的需求,各大 数据库厂商借鉴面向对象技术,发展了对象关系型数据库管理系统 , 增加空间数据类型及相关函数,从而将空间数据 的存储、查询和索引 从 传统GIS软件厂商的 空间数据引擎中间件转移到了数据库管理系统中, 让用 户 可以 使用 扩充的 空间数据类型和函数的标准扩展型SQL语言来操作空间数据。 </P>
<P>SQL Server 2008作为微软公司的新一代智能化数据存储平台,提供了对空间数据存储、查询、索引的原生支持,在其强大的.NET平台支持下,可以很容易的开发操控空间数据的应用程序。而免费的的SQL Server 2008 Express中依然提供了空间数据扩展支持,这很大程度上方便了基于Windows平台桌面空间数据应用程序的开发。以下笔者将一步一步使用C#和SQL Server 2008 CTP版(社区技术版)开发一个简单的操控空间数据的应用程序。 </P>
<P><BR>2.  程序功能描述 </P>
<P>程序目标功能主要分为三部分: </P>
<P>(1) 创建三个存储点、线、面的数据库表并在相应的表中添加空间数据; </P>
<P>(2) 绘制数据库中所有图形; </P>
<P>(3) 绘制指定矩形范围内的图形。 </P>
<P><BR>3.  创建项目并实现用户界面 </P>
<P>首先,使用SQL Server 2008创建一个名为SQLSpatial的数据库,用Visual C# 2005创建一个名为SQLSpatial的Windows窗体应用程序项目。将Form1的窗体标题改为“SQL Server 2008空间数据库示例”,修改窗体背景色为白色,并为其添加菜单。完成后的用户界面如图1所示。 </P>

<P><BR>4.  编写代码 </P>
<P>(1)  在Visual Studio的解决方案管理器中右击SQLSpatial项目添加程序集 Microsoft.SqlServer.Types.dll 的引用,这是对空间数据类型geometry和geography的支持库。程序集位于SQL Server 2008安装实例的MSSQL\Binn目录下,例如笔者的目录为C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER2008\MSSQL\Binn。 </P>
<P>(2)  在程序Form1窗体类的代码中加入以下命名空间的引用。 </P>
<P>using  System.Data.SqlClient;       //使用SQL Server .NET提供者命名空间 </P>
<P>using  Microsoft.SqlServer.Types;     //引用空间数据类型对象命名空间 </P>
<P>using  System.Drawing.Drawing2D;    //引用GDI+绘图类命名空间 </P>
<P>(3)  双击各个菜单添加消息响应函数并输入代码。 </P>
<P>A、 创建PointTable表并添加点数据的函数代码如下: </P>
<P>             //创建数据库连接字符串 </P>
<P>             SqlConnectionStringBuilder  conBuilder =  new   SqlConnectionStringBuilder (); </P>
<P>            conBuilder.DataSource =  @"KFB-AS\SQLSERVER2008" ;       // 客户服务器名称 </P>
<P>            conBuilder.InitialCatalog =  "SQLSpatial" ;             // 数据库名称 </P>
<P>            conBuilder.IntegratedSecurity =  true ; </P>
<P>             try </P>
<P>            {     using  ( SqlConnection  con =  new   SqlConnection (conBuilder.ConnectionString)) </P>
<P>                 {    //创建PointTable表 </P>
<P>                     string  cmdStr = </P>
<P>  "IF OBJECT_ID ('dbo.PointTable','U') IS NOT NULL DROP TABLE dbo.PointTable" ; </P>
<P>                     SqlCommand  cmd =  new   SqlCommand (cmdStr, con); </P>
<P>                    con.Open(); </P>
<P>                    cmd.ExecuteNonQuery(); </P>
<P>                    cmd.CommandText  </P>
<P>=  "CREATE TABLE PointTable(ID int IDENTITY(1,1), Geometry geometry)" ; </P>
<P>                    cmd.ExecuteNonQuery(); </P>
<P>                     //添加点数据 </P>
<P>                     SqlDataAdapter  adapter =  new   SqlDataAdapter ( "SELECT * FROM PointTable" , con); </P>
<P>                     SqlCommandBuilder  cmdBuilder =  new   SqlCommandBuilder (adapter); </P>
<P>                     DataSet  ds =  new   DataSet (); </P>
<P>                    adapter.Fill(ds,  "PointTable" ); </P>
<P>                     for  ( int  i = 0; i < 1000; i += 10) </P>
<P>                     {    string  wkt =  String .Format( "POINT({0} {1})" , i + 100, i + 20); </P>
<P>                         SqlGeometry  g =  new   SqlGeometry (); </P>
<P>                        g =  SqlGeometry .Parse(wkt); </P>
<P>                         DataRow  drow = ds.Tables[ "PointTable" ].NewRow(); </P>
<P>                        drow[ "Geometry" ] = g; </P>
<P>                        ds.Tables[ "PointTable" ].Rows.Add(drow); </P>
<P>                    } </P>
<P>                    adapter.Update(ds,  "PointTable" ); </P>
<P>                } </P>
<P>                 MessageBox .Show( "数据库PointTable中已经成功添加点数据!" ); </P>
<P>            } </P>
<P>             catch  ( Exception  ex) </P>
<P>            {   MessageBox .Show(ex.Message); </P>
<P>    } </P>
<P>B、 创建LineTable表并添加线数据的主要代码如下: </P>
<P>                     //创建LineTable表 </P>
<P>                     string  cmdStr =  </P>
<P>"IF OBJECT_ID ('dbo.LineTable','U') IS NOT NULL DROP TABLE dbo.LineTable" ; </P>
<P>                     SqlCommand  cmd =  new   SqlCommand (cmdStr, con); </P>
<P>                    con.Open(); </P>
<P>                    cmd.ExecuteNonQuery(); </P>
<P>                    cmd.CommandText =  </P>
<P>"CREATE TABLE LineTable(ID int IDENTITY(1,1), Geometry geometry)" ; </P>
<P>                    cmd.ExecuteNonQuery(); </P>
<P>                     //添加线数据 </P>
<P>                     SqlDataAdapter  adapter =  new   SqlDataAdapter ( "SELECT * FROM LineTable" , con); </P>
<P>                     SqlCommandBuilder  cmdBuilder =  new   SqlCommandBuilder (adapter); </P>
<P>                     DataSet  ds =  new   DataSet (); </P>
<P>                    adapter.Fill(ds,  "LineTable" ); </P>
<P>                     for  ( int  i = 0; i < 1000; i += 50) </P>
<P>                     {   string  wkt =  String .Format( "LINESTRING({0} {1},{2} {3})" , 20, i, 300, i); </P>
<P>                         SqlGeometry  g =  new   SqlGeometry (); </P>
<P>                        g =  SqlGeometry .Parse(wkt); </P>
<P>                         DataRow  drow = ds.Tables[ "LineTable" ].NewRow(); </P>
<P>                        drow[ "Geometry" ] = g; </P>
<P>                        ds.Tables[ "LineTable" ].Rows.Add(drow); </P>
<P>                    } </P>
<P>                    adapter.Update(ds,  "LineTable" );           </P>
<P>C、 创建PolygonTable表并添加多边形数据的主要代码如下: </P>
<P>               string  cmdStr = </P>
<P>                  "IF OBJECT_ID ('dbo.PolygonTable','U') IS NOT NULL DROP TABLE dbo.PolygonTable" ; </P>
<P>                     SqlCommand  cmd =  new   SqlCommand (cmdStr, con); </P>
<P>                    con.Open(); </P>
<P>                    cmd.ExecuteNonQuery(); </P>
<P>                    cmd.CommandText =  </P>
<P>"CREATE TABLE PolygonTable(ID int IDENTITY(1,1), Geometry geometry)" ; </P>
<P>                    cmd.ExecuteNonQuery(); </P>
<P>                     //添加多边形数据 </P>
<P>                     SqlDataAdapter  adapter =  new   SqlDataAdapter ( "SELECT * FROM PolygonTable" , con); </P>
<P>                     SqlCommandBuilder  cmdBuilder =  new   SqlCommandBuilder (adapter); </P>
<P>                     DataSet  ds =  new   DataSet (); </P>
<P>                    adapter.Fill(ds,  "PolygonTable" ); </P>
<P>                     for  ( int  i = 0; i < 1000; i += 60) </P>
<P>                     {   string  wkt =  </P>
<P>String .Format( "POLYGON(({0} {1},{2} {3},{4} {5},{6} {7},{8} {9}))" , i, i, i + 50, i, i + 50, i + 50, i, i + 50, i, i); </P>
<P>                         SqlGeometry  g =  new   SqlGeometry (); </P>
<P>                        g =  SqlGeometry .Parse(wkt); </P>
<P>                         DataRow  drow = ds.Tables[ "PolygonTable" ].NewRow(); </P>
<P>                        drow[ "Geometry" ] = g; </P>
<P>                        ds.Tables[ "PolygonTable" ].Rows.Add(drow); </P>
<P>                    } </P>
<P>                    adapter.Update(ds,  "PolygonTable" ) ;    </P>
<P>(4) 为Form1窗体类添加两个私有绘图函数用于使用GDI+在窗品中绘制图形; </P>
<P>private   void  DrawAllFeature( Graphics  gdi) </P>
<P>           {       </P>
<P>          // 代码为DrawSelect(Graphics gid)函数中去掉带下划线部分的代码 </P>
<P>} </P>
<P>          private   void  DrawSelect( Graphics  gdi) </P>
<P>           {   //创建数据库连接字符串 </P>
<P>             SqlConnectionStringBuilder  conBuilder =  new   SqlConnectionStringBuilder (); </P>
<P>            conBuilder.DataSource =  @"KFB-AS\SQLSERVER2008" ;         // 客户服务器名称 </P>
<P>            conBuilder.InitialCatalog =  "SQLSpatial" ;               // 数据库名称 </P>
<P>            conBuilder.IntegratedSecurity =  true ; </P>
<P>             //创建绘图区域对象 </P>
<P>              string  wkt =  "POLYGON((60 60,200 60,200 200,60 200,60 60))" ; </P>
<P>             SqlGeometry  gRect =  SqlGeometry .Parse(wkt); </P>
<P>             try </P>
<P>            {   using  ( SqlConnection  con =  new   SqlConnection (conBuilder.ConnectionString)) </P>
<P>                 {     con.Open(); </P>
<P>                     //绘多边形数据 </P>
<P>                   SqlDataAdapter  adPolygon =  new   SqlDataAdapter ( "SELECT * FROM PolygonTable" , con); </P>
<P>                     SqlCommandBuilder  cmdBuilderPolygon =  new   SqlCommandBuilder (adPolygon); </P>
<P>                     DataSet  ds =  new   DataSet (); </P>
<P>                    adPolygon.Fill(ds,  "PolygonTable" ); </P>
<P>                     foreach  ( DataRow  row  in  ds.Tables[ "PolygonTable" ].Rows) </P>
<P>                    {   SqlGeometry  g = ( SqlGeometry )row[ "Geometry" ]; </P>
<P>                         //如果被绘图区域包含或与绘图区域相交则绘图形 </P>
<P>                         if  (gRect.STIntersects(g) || gRect.STContains(g)) </P>
<P>                        {   int  pointSum = ( int )g.STNumPoints(); </P>
<P>                             PointF [] points =  new   PointF [pointSum]; </P>
<P>                             byte [] pointTypes =  new   byte [pointSum]; </P>
<P>                             for  ( int  i = 0; i < pointSum; i++) </P>
<P>                            {   points.X = ( float )g.STPointN(i + 1).STX; </P>
<P>                                points.Y = ( float )g.STPointN(i + 1).STY; </P>
<P>                                pointTypes = ( byte ) PathPointType .Line; </P>
<P>                            } </P>
<P>                             GraphicsPath  path =  new   GraphicsPath (points, pointTypes); </P>
<P>                            gdi.FillPath( Brushes .Red, path); </P>
<P>                        } </P>
<P>                    } </P>
<P>                     //绘线数据 </P>
<P>                     SqlDataAdapter  adLine =  new   SqlDataAdapter ( "SELECT * FROM LineTable" , con); </P>
<P>                     SqlCommandBuilder  cmdBuilderLine =  new   SqlCommandBuilder (adLine); </P>
<P>                    adLine.Fill(ds,  "LineTable" ); </P>
<P>                     using  ( Pen  bluePen =  new   Pen ( Color .Blue, 2)) </P>
<P>                    {   foreach  ( DataRow  row  in  ds.Tables[ "LineTable" ].Rows) </P>
<P>                        {   SqlGeometry  g = ( SqlGeometry )row[ "Geometry" ]; </P>
<P>                             //如果被绘图区域包含或与绘图区域相交则绘图形 </P>
<P>                             if  (gRect.STIntersects(g) || gRect.STContains(g)) </P>
<P>                            {gdi.DrawLine(bluePen,  new   PointF (( float )g.STPointN(1).STX,   ( float )g.STPointN(1).STY),   new   PointF (( float )g.STPointN(2).STX,    ( float )g.STPointN(2).STY)); </P>
<P>                            } </P>
<P>                        } </P>
<P>                    } </P>
<P>                     //绘点数据 </P>
<P>                     SqlDataAdapter  adPoint =  new   SqlDataAdapter ( "SELECT * FROM PointTable" , con); </P>
<P>                    adPoint.Fill(ds,  "PointTable" ); </P>
<P>                     using  ( Pen  greenPen =  new   Pen ( Color .Green, 2)) </P>
<P>                    {   foreach  ( DataRow  row  in  ds.Tables[ "PointTable" ].Rows) </P>
<P>                        {   SqlGeometry  g = ( SqlGeometry )row[ "Geometry" ]; </P>
<P>                             if  (gRect.STIntersects(g) || gRect.STContains(g)) </P>
<P>                            {   // 绘一个半径为1的圆表示点 </P>
<P>        gdi.DrawEllipse(greenPen, ( float )g.STPointN(1).STX - 1, ( float )g.STPointN(1).STY - 1, 2, 2); </P>
<P>                            } </P>
<P>                        } </P>
<P>                    } </P>
<P>                } </P>
<P>            } </P>
<P>             catch  ( Exception  e) </P>
<P>             {   essageBox .Show(e.Message);   } </P>
<P>  } </P>
<P>(5) 添加绘图消息响应代码 </P>
<P>A、 为Form1添加一个私有字段用于控制绘制所有图形还是绘制矩形范围图形; </P>
<P>private   int  drwType=-1; </P>
<P>B、为Form1添加OnPaint消息响应函数并添加下列代码 </P>
<P>               if (drwType==1) </P>
<P>                 DrawAllFeature(e.Graphics); </P>
<P>             else   if (drwType==2) </P>
<P>       DrawSelect(e.Graphics); </P>
<P>C、在菜单“绘数据库中所有图形”的消息响应函数中添加如下代码: </P>
<P>            drwType=1;       </P>
<P>             this .Invalidate(); </P>
<P>D、在菜单“绘60,60 200,200矩形范围内的图形”的消息响应函数中添加如下代码: </P>
<P>            drwType = 2 ;       </P>
<P>    this .Invalidate(); </P>
<P>5. 程序运行结果 </P>
<P>依次点击菜单创建点、线、面数据,然后执行“ 绘数据库中所有图形”菜单后的运行结果如图2所示。执行“绘60,60 200,200矩形范围内的图形”将绘制在矩形(60,60 200,200)范围内的图形或与该矩形相交的图形,运行结果如图3所示。 </P>
<P>          </P>
<P>图2.绘制所有的图形数据           图3. 绘制指定矩形范围的图形数据 </P>
<P>6.小结 </P>
<P>程序通过引入 Microsoft.SqlServer.Types.dll 程序集,使用geometry空间数据类型的封装类SqlGeometry的方法来完成空间对象的创建并存入数据库中,在判断图形是否绘制时使用了SqlGeometry类的方法很容易的完成,最后将数据库中的图形读出并使用GDI+完成图形绘制。SQL Server 2008在空间数据支持上提供了许多强大的功能,使用SQL Server 2008提供的空间数据类型对象,利用强大的开发工具Visual Studio开发工具基于.NET平台及现代的面向对象编程语言C#可快速的开发出操控空间数据的应用程序。本文意在抛砖引玉,欠妥之处,敬请指正。 </P>
<P>参考文献: </P>
<P>[1]Visual C# 2005文件IO与数据存取秘诀——章立民研究室 著 </P>
<P>[2]SQL Server 2005数据库开发实战——章立民研究室著 </P>
<P>[3]GDI+图形程序设计——Mahesh Chand 著 </P>
<P>[4]为我们的世界建模-ESRI地理数据库设计指南——Michael Zeiler著 </P>

<P>本文来自CSDN博客,转载请标明出处:<a href="http://blog.csdn.net/ynchlss/archive/2008/03/27/2223176.aspx" target="_blank" >http://blog.csdn.net/ynchlss/archive/2008/03/27/2223176.aspx</A></P>
喜欢0 评分0
linkyang
路人甲
路人甲
  • 注册日期2009-04-21
  • 发帖数28
  • QQ
  • 铜币192枚
  • 威望0点
  • 贡献值0点
  • 银元0个
1楼#
发布于:2009-06-24 14:33
<img src="images/post/smile/dvbbs/em01.gif" /><img src="images/post/smile/dvbbs/em02.gif" />
举报 回复(0) 喜欢(0)     评分
游客

返回顶部