C#开发SQLServer的Geometry和Geography存储

原文:C#开发SQLServer的Geometry和Geography存储

SQL Server2008推出后最大的变化就是提供了支持空间数据存储的Geometry和Geography,这个也是如果将ArcSDE和SQLServer数据库相结合后可以供用户选择的一种数据存储模式,因为SQLServer2008前的数据库版本都是BLOB来存储空间数据对象的,目前没有测试来判断哪个性能更优,但是个人倾向于Geometry和Geography。

使用这两种存储,一个优点就是,使用SQL Server数据库也可以像使用Oracle、PostgreSQL一样,使用SQL来进行操作。

在以前的文章中我们也介绍了关于SQL的操作,但是都是在SQl Server的manger studio里面进行的

相关参考:ArcSDE for SQLServer的SQL操作  

本文介绍的如何使用编程的方式C#来对SQL Server空间数据存储的Geometry和Geography来进行操作。

首先我们需要引用一个Microsoft.SqlServer.Types.dll,

该文件根据32Bit和64Bit的不同分布情况不同

32Bit:C:\Program Files \Microsoft SQL Server\100\SDK\Assemblies

64Bit:C:\Program Files (x86)\Microsoft SQL Server\100\SDK\Assemblies

注意如果你的SQL Server是2008和2012也是有相关区别的。

引用相关dll我们就可以进行开发了

以下代码环境:VS2010,引用dll版本SQL Server2012

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.SqlServer.Types;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using System.Configuration;

namespace SQL
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

           object s= GetSRID("sde101", "sde", "CHINACITYTABLE");
        }
        //连接串
        string connstring = "Data Source=192.168.100.111;Initial Catalog=sde101;Persist Security Info=True;User ID=sde;Password=sde";
        //获得数据连接
        public SqlConnection GetSQLConnection()
        {
            try
            {
                return new SqlConnection(connstring);
            }
            catch (Exception)
            {
                return null;
            }
        }

        //将Geometry对象转换为WKT串
        public  void QuerytoWKT()
        {
            string sql = "select shape from xzq where objectid=45";
            SqlGeometry g = GetGeometry(sql);
            if (g != null)
            {
                //以WKT输出
                Console.WriteLine(g);
            }
        }
        //获得Geometry对象
        /// <summary>
        /// 直接使用SQL语句获得SQLGeometry对象
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>
        public SqlGeometry GetGeometry(string sql)
        {
            try
            {

                SqlCommand cmd = GetCommand(sql);
                SqlDataReader reader = cmd.ExecuteReader();
                while (reader.Read())
                {
                    SqlBytes sb = reader.GetSqlBytes(0);
                    //Deserialize方法只有引用SQLServer2012的dll才能使用,2008不支持 
                    SqlGeometry g = SqlGeometry.Deserialize(sb);
                    return g;
                }
                return null;
            }

            catch (Exception e)
            { return null; }
        }
        /// <summary>
        /// 根据WKT串获得SQLGeometry对象
        /// </summary>
        /// <param name="sWKT"></param>
        /// <param name="sSRID"></param>
        /// <returns></returns>
        public SqlGeometry GetGeometry(string sWKT, int sSRID)
        {
            // var sql = "POLYGON((509827.650 3848402.022,509763.336 3847282.564,509268.926 3847640.308,509827.650 3848402.022))";

            SqlChars polyText = new SqlChars(sWKT);
            return SqlGeometry.STGeomFromText(polyText, sSRID);
        }
        public SqlCommand GetCommand(string sql)
        {
            SqlConnection conn = GetSQLConnection();
            conn.Open();
                  SqlCommand cmd = new SqlCommand(sql, conn);
                  return cmd;
        }
        //增删改直接写上不同的SQL语句即可
        public void EditData()
        {
            try
            {
                string sWKT = "POLYGON((513132.704 3847868.592,513860.309 3846638.277,512682.911 3846598.589,513132.704 3847868.592))";
                string sql = "insert xzq (objectid,shape) values(11111,'"+sWKT+"')";
                SqlCommand cmd = GetCommand(sql);
                cmd.ExecuteNonQuery();
            }
            catch (Exception e)
            { }
        }
        //获得相交数据
        /// <summary>
        /// Unable to load DLL 'SqlServerSpatial110.dll': 找不到指定的模块。 (Exception from HRESULT: 0x8007007E)
        /// </summary>
        public void GetIntersections()
        {
            try
            {
                string sql1 = "select shape from xzq where objectid=86";
                string sql2 = "select shape from xzq where objectid=71";
                SqlGeometry g1 = GetGeometry(sql1);
                SqlGeometry g2 = GetGeometry(sql2);

                //获得相交的图形
                SqlGeometry g3 = g1.STIntersection(g2);
                if (g3 != null)
                {
                    //以WKT输出
                    Console.WriteLine(g3);
                }
            }
            catch (Exception e)
            { }
        }
        //获得两点距离
        public string GetDistance(SqlGeometry p1, SqlGeometry p2)
        {
            return p1.STDistance(p2).ToString();
        }

        /// <summary>
        ///  //根据表名获得SRID
        ///  主要是直接进入GDB_ITEMS表里面获得制定表对象的SRID值
        ///  GDB_ITEMS表是安装了ArcSDE后才有的表
        ///  select shape from  [sde101].[sde].[CHINACITYTABLE]
        /// </summary>
        /// <param name="sTableName"></param>
        /// <param name="sDatabasename"></param>
        /// <param name="sUser"></param>
        /// <returns></returns>
        public object GetSRID(string sDatabasename,string sUser,string sTableName)
        {
            //如果找不到,返回0
            object SRID = null;
            //如果熟悉ArcSDE的库的表结构,只要是解析相关的XML文件,来获得SRID
            string sql = "SELECT Definition.value('(/DEFeatureClassInfo/SpatialReference/LatestWKID)[1]','nvarchar(max)') FROM "+
                sDatabasename+"."+sUser+".[GDB_ITEMS] WHERE Name='"+sDatabasename+"."+sUser+"."+sTableName+"'";
              SqlCommand cmd = GetCommand(sql);
                SqlDataReader reader = cmd.ExecuteReader();
                while (reader.Read())
                {
                   SRID= reader.GetSqlValue(0);
                }
            return SRID;
        }
    }
}

以上代码有几个需要说明

1:在使用Geometry对象解析过程中,使用Deserialize,该方法只有SQL Server2012有,如果你使用SQL Server2008没有该方法

2:Geometry和Geography的区别在于你所使用的投影是平面坐标和地理坐标

3:在使用空间关系中,系统会提示

Unable to load DLL 'SqlServerSpatial110.dll': 找不到指定的模块。 (Exception from HRESULT: 0x8007007E)

这是因为,Microsoft.SqlServer.Types.dll文件需要使用操作系统C:\Windows\System32\SqlServerSpatial110.dll(同样安装了SQL Server不同版本,在该路径下的版本号不一样,110代表2012版本),该dll不是加载的,是需要存储放在系统路径下的,注意两者的版本一致。

4:获得SRID,我是直接从ArcSDE的Schema的XML来获得的。

最后强调一下,因为这是Mircosoft提供的空间存储对象,所以相关帮助查看微软帮助即可。

http://technet.microsoft.com/zh-cn/library/ee642046(v=sql.105).aspx

相关dll下载地址

更深一步,如果对该方面的内容非常感兴趣,建议看看

SQL Server Spatial Tools

以下地址有相关源代码下载

-------------------------------------------------------------------------------------------------------
版权所有,文章允许转载,但必须以链接方式注明源地址,否则追究法律责任!
------------------------------------------------------------------------------------------------------

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-09-10 15:14:07

C#开发SQLServer的Geometry和Geography存储的相关文章

怎么把notes开发的系统中的数据存储到sql-server中????

问题描述 怎么把notes开发的系统中的数据存储到sql-server中???? 解决方案 解决方案二:方法有很多种解决方案三:用LEI就可以解决方案四:SubClick(SourceAsButton)OnErrorGotoErrorHandleDimwsAsNewNotesUIWorkspaceDimsessionAsNewNotesSessionDimdbAsNotesDatabaseDimviewAsNotesViewDimcolumnAsNotesViewColumnDimdocAsNo

PostGIS 距离计算规范 - 投影 与 球 坐标系, geometry 与 geography 类型

标签 PostgreSQL , PostGIS , 球坐标 , 平面坐标 , 球面距离 , 平面距离 背景 PostGIS中有两种常用的空间类型geometry和geography,这两种数据类型有什么差异,应该如何选择? 对于GIS来说,首先是坐标系,有两种:一种是球坐标(地理坐标),另一种是平面坐标(投影坐标). 球坐标通常用于计算,平面坐标通常用于展示(也可以计算). 投影坐标是从球坐标投影后展开得来(用一个圆柱将地球包起来,把地球当成会发光的光源,投影后,将圆柱展开得到),投影的范围越大

Windows Phone开发(29):隔离存储C

原文:Windows Phone开发(29):隔离存储C 本文是隔离存储的第三节,大家先喝杯咖啡放松,今天的内容也是非常简单,我们就聊一件东东--用户设置. 当然了,可能翻译为应用程序设置合适一些,不过没关系,只要大家明白,它就是用于保存我们的应用程序的设置信息就行了. 它属于字典集合,每一项保存的数据都以键-值对的形式存储,键值是字符串类型,不能为null,注意啊,不然会引发异常,当然,估计也没有人这么无聊,把空值保存. 使用方法很简单,通过IsolatedStorageSettings的Ap

Windows Phone开发(27):隔离存储A

原文:Windows Phone开发(27):隔离存储A 在很多资料或书籍上都翻译为"独立存储",不过,我想了一下,决定将IsolatedStorage翻译为"隔离存储",我想这样会更方便大家对这一概念的理解. 关于何为隔离存储,按照固有习惯,我不希望作太多理论上的解释,一来理论化的东西容易把简单的事情变得复杂化,二来,就算把理论知识说得有多完美,相信大家都没兴趣看,就算你有兴趣也会一头雾水. 隔离存储不是WP特有的,在Silverlight或WPF中也有,而且,更

使用java开发阿里云OSS开放云存储服务

购买了阿里云后,我们发现一般ECS的存储空间都比较小,当然我们可以动态的扩展一些存储空间.但是作为开发者,我们在日常使用中需要一些更大的灵活性,因此就需要我们自己对OSS存储有一些自己的扩展.今天就为大家分享一下如何使用java来对接阿里云的OSS存储服务. OSS产品概述 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量.安全.低成本.高可靠的云存储服务.您可以通过调用 API,在任何应用.任何时间.任何地点上传和下载数据,也可以通过 Web

iOS开发UI篇—ios应用数据存储方式(偏好设置)

一.简单介绍 很多iOS应用都支持偏好设置,比如保存用户名.密码.字体大小等设置,iOS提供了一套标准的解决方案来为应用加入偏好设置功能 每个应用都有个NSUserDefaults实例,通过它来存取偏好设置.比如,保存用户名.字体大小.是否自动登录 存储位置: 存储形式: 二.代码示例 1.storyboard 2.代码 1 // 2 // YYViewController.m 3 // 01-偏好设置 4 // 5 // Created by apple on 14-6-7. 6 // Cop

iOS开发UI篇—ios应用数据存储方式(XML属性列表-plist)

一.ios应用常用的数据存储方式 1.plist(XML属性列表归档) 2.偏好设置 3.NSKeydeArchiver归档(存储自定义对象) 4.SQLite3(数据库,关系型数据库,不能直接存储对象,要编写一些数据库的语句,将对象拆开存储) 5.Core Data(对象型的数据库,把内部环节屏蔽) 二.应用沙盒 每个iOS应用都有⾃己的应⽤沙盒(应用沙盒就是文件系统目录),与其他文件系统隔离.应⽤必须待在⾃己的沙盒里,其他应用不能访问该沙盒(提示:在IOS8中已经开放访问) 应⽤沙盒的文件系

iOS开发UI篇—ios应用数据存储方式(归档)

一.简单说明 在使用plist进行数据存储和读取,只适用于系统自带的一些常用类型才能用,且必须先获取路径相对麻烦: 偏好设置(将所有的东西都保存在同一个文件夹下面,且主要用于存储应用的设置信息) 归档:因为前两者都有一个致命的缺陷,只能存储常用的类型.归档可以实现把自定义的对象存放在文件中. 二.代码示例 1.文件结构 2.代码示例 YYViewController.m文件 1 // 2 // YYViewController.m 3 // 02-归档 4 // 5 // Created by

[网站开发]菜鸟求问,请问网页一般是怎么存储的???

问题描述 [网站开发]请问网页一般是怎么存储的???我看到新浪每天都会产生许多新的网页,像下面这个链接http://news.sina.com.cn/c/2011-03-16/002022121008.shtml.这些网页的内容是每一次我点击链接的时候都从数据库拼凑出信息组合而成的网页吗?还是已经声称好了的,然后存储在某个地方??是存在数据库还是作为普通文件存在硬盘???请有经验者给出解答! 解决方案 解决方案二:都是已经生成好的静态页面解决方案三:右键查看源码能看见的是静态不能的是读的数据解决