技术开发 频道

使用空间数据类型与Virtual Earth

【IT168 技术文档】
使用 Microsoft SQL Server 2008 空间数据类型与Virtual Earth的集成
目录
准备工作 1
练习 1: 以GML 格式返回空间数据 3
练习 2: 创建一个GeoRSS 订阅源 6
练习 3: 使用Virtual Earth VEMap 控件 10

准备工作
预计完成本实验所需的时间
60 分钟

目标
在完成本实验后,您将可以:
创建存储过程,以GML格式返回空间数据;
创建一个HTPP的 Handler返回一个空间数据的GeoRSS订阅源;
创建一个Web页面,将Microsoft SQL Server 2008 的空间数据类型与Microsoft Virtual Earth™ VEMap 控件进行集成。


先决条件
在完成本实验前,您必须:
具有编写Transact-SQL 脚本与使用SQL Server Management Studio的相关经验。
熟悉SQL Server 2008当中的空间数据类型。
具有使用Microsoft Visual Studio开发Microsoft ASP.NET 应用程序的相关经验。
具有使用Microsoft JScript进行客户端Web开发的相关经验。


实验场景
Adventure Works Cycles 为遍布美国的许多商店提供自行车产品。您被命令开发一个Web页面,使得客户可以使用这个页面来定位所有销售Adventure Works产品的商店。另外,用户必须能够找到一个特定地点100公里范围内的所有商店。有关商店位置的地里信息数据被存储在一个SQL Server 2008 数据库中,而且您必须将这些搜索结果显示在页面中的一个Virtual Earth 地图当中。

虚拟机环境
从开始菜单或桌面上启用Microsoft Virtual PC 。如果Virtual PC 控制台没有启用,请查看系统托盘,然后双击系统托盘当中的Microsoft Virtual PC 。

选择Sql08 然后点击Start。

在虚拟机运行起来后,可以通过点击右Alt+Del 来向虚拟机发送一个Ctrl+Alt+Del 命令。
在登录窗口中,输入以下信息:
User name: administrator
Password: password01!

注意: 本实验要求虚拟机可以连接到Internet。
 

练习 1: 以GML 格式返回空间数据

在本练习中,您将创建一个存储过程,并以地理标记语言(GML)格式返回空间数据。GML是由Open Geospatial Consortium (OGC) 为在不同应用程序与系统之间交换空间数据信息所定义的标准。SQL Server支持的空间数据类型支持作为空间数据类型实例的源,并支持作为空间数据传递的格式。这种对于GML的支持,使得在SQL Server和其它地理信息系统(如Microsoft Virtual Earth)之间进行数据交换非常容易。

创建一个包含空间数据的数据库

启动SQL Server Management Studio。当出现提示时,使用Windows Authentication连接到 (local) 数据库实例。
在C:\SQLHOLs\Spatial and VE\Starter 目录中,打开Create DB.sql 查询文件。
查看这个脚本当中的Transact-SQL 代码,注意,这个脚本执行了下面一些任务:

删除并重新创建一个叫做StoreData的数据库。

创建一个叫做Stores 的数据表,包含一个类型为geography 名为StoreLocation的数据列。

在刚刚创建的StoreLocation 数据列上创建一个空间数据索引。
 

向Stores 表中插入一些数据行。每条记录都包含一个StoreLocation 值,它表示一个由经度和纬度坐标定义商店的地理位置。

点击Execute ,运行脚本。如果已经存在了StoreData 数据库,则可能会出现一些错误,忽略这些错误。
保持SQL Server Management Studio 打开,后面的步骤中要继续使用。

创建一个存储过程返回所有商店

点击 New Query 创建一个新的查询。如果出现提示,使用Windows Authentication连接到 (local) 数据库引擎。
在查询编辑器中输入下面的Transact-SQL 代码。

USE StoreData
GO
CREATE PROCEDURE GetStoresGML
AS
-- Return the store location geography data as GML
SELECT StoreName,
StoreAddress
+ ', Tel:' + StorePhone AS ContactDetails,
StoreLocation.AsGml()
As StoreGML
FROM Stores
GO

注意: 在这段代码当中,使用了geography 数据类型的AsGml 方法来以GML格式返回地理信息数据。
点击Execute 运行脚本。

在CREATE PROCEDURE 语句后面,添加下面的代码,测试存储过程。
EXECUTE GetStoresGML
选中刚刚输入的EXECUTE 语句,然后点击Execute 运行选中的代码。
在结果面板中,点击任意StoreGML 值,来在XML查看器中查看空间数据的GML 表示形式。
关闭XML查看器,然后返回查询编辑器中。

创建一个存储过程来返回指定位置附近的商店

在上面的过程中输入的EXECUTE 语句下面,添加下面的Transact-SQL 代码:

CREATE PROCEDURE GetNearbyStoresGML @Lat nvarchar(10), @Long nvarchar(10)
AS
-- Create a point geography instance based on the supplied location
DECLARE @SearchPoint geography
SET @SearchPoint = geography::Point(@Lat, @Long, 4326)

-- Create a polygon geography instance by adding a 100km buffer to the point
DECLARE @SearchArea geography
SET @SearchArea = @SearchPoint.STBuffer(100000)

--Return the search area and all store locations that intersect it
SELECT 'Search Area', '100 KM radius', @SearchArea.AsGml()
UNION ALL
SELECT StoreName,
StoreAddress
+ ', Tel:' + StorePhone AS ContactDetails,
StoreLocation.AsGml()
As StoreGML
FROM Stores
WHERE StoreLocation.STIntersects(@SearchArea) = 1
GO

注意: 这段代码创建一个geography 实例,它包含了一个基于经度和纬度的地理坐标,这个坐标将作为参数传递到存储过程当中。它使用geography 数据类型的STBuffer方法来创建了一个geography多边形实例,用来表示一个以待搜索点为圆心100公里为半径的圆。最后,这段代码返回了一个geography实例的GML表示,它使用geography数据类型的STIntersects 方法,返回了所有与搜
索区域相交的商店位置。

选择刚刚创建的CREATE PROCEDURE 语句,然后点击Execute 运行选中的脚本。

在CREATE PROCEDURE 语句下面,添加下面的代码测试存储过程:

EXECUTE GetNearbyStoresGML '34.000000', '-118.000000'
选择刚刚添加的EXECUTE 语句,然后点击Execute 运行选中的代码。
在结果面板中,点击第一个XML值,在XML查看器中查看搜索区域的GML表示形式。
关闭XML查看器,返回查询编辑器。
将查询脚本保存为C:\SQLHOLs\Spatial and VE\Starter\StoredProcs.sql,,然后关闭SQL Server Management Studio。
 

练习 2: 创建一个GeoRSS 订阅源

在本练习中,您将在ASP.NET Web应用程序当中实现一个HTTP Handler,并用它来返回一个GeoRSS订阅源。GeoRSS 是一种包含地理信息数据的RSS订阅标准格式,它定义一个特定的格式,叫做GeoRSS GML,用来在订阅中包含GML格式的数据。客户端应用程序可以以普通的RSS源的方式来订阅GeoRSS源。而以GeoRSS格式返回的数据则可以被轻松的导入到Microsoft Virtual Earth VEMap控件当中。

实现一个HTTP Handler

启用 Microsoft Visual Studio 2008。

打开File 菜单,点击Open,点击Web Site,然后打开C:\SQLHOLs\Spatial and VE\Starter\StoreFinderSite Web 站点。

在Solution Explorer中,展开App_Code目录,然后双击GeoRSSHandler.vb 在代码编辑器中打开它。

注意: HTTP Handler 是一个代码模块,它可以处理到Web应用程序的HTTP 请求。通常,到一个Web应用程序的HTTP请求是由一些默认的ASP.NET 请求处理器所处理的,但是您可以为特定的扩展名创建自定义的处理器。这时,您将实现一个请求处理器,它将会返回.georss为扩展名为的处理结果。

查看现有的代码。用来处理请求的函数叫做ProcessRequest。注意,这段代码还没有完成,有些代码需要继续填充完整。

在Build the GeoRSS feed注释下面,添加下面代码开始构建由HTTP Handler返回的GeoRSS 源。

rssOutput.AppendLine("<feed xmlns='http://www.w3.org/2005/Atom'")
rssOutput.AppendLine("xmlns:georss
='http://www.georss.org/georss'")
rssOutput.AppendLine("xmlns:gml
='http://www.opengis.net/gml'>")
rssOutput.AppendLine("
<title>Stores</title>")
rssOutput.AppendLine("
<subtitle>Store Locations</subtitle>")
rssOutput.AppendLine("
<link href='http://localhost/storefindersite/'/>")
rssOutput.AppendLine("
<updated>" + System.DateTime.Now + "</updated>")
rssOutput.AppendLine("
<author>")
rssOutput.AppendLine("
<name>SQL Server</name>")
rssOutput.AppendLine("
</author>")

在Open a connection to the database注释下面,添加下面的代码。
sqlConn.Open()

在Use the GetStoresGML stored proc to get all stores by default注释下面,添加下面的代码。
spName = "GetStoresGML"

注意: 默认情况下, 到这个HTTP Handler的请求处理将会调用GetStoresGML 存储过程,并将返回包所有商店的GeoRSS 源。
在 If a searchFrom parameter is provided, use GetNearbyStores      and add the provided lat and lon coordinates as parameters注释下面,添加下面的代码。

Dim searchFrom As String = context.Request.QueryString("SearchFrom")
If Not searchFrom Is Nothing Then
spName
= "GetNearbyStoresGML"
Dim latLong()
As String = Split(searchFrom, ",", 2)
cmd.Parameters.
Add(New SqlParameter("Lat", latLong(0)))
cmd.Parameters.
Add(New SqlParameter("Long", latLong(1)))
End If

注意: 如果请求包含一个参数,叫做SearchFrom(它将会包含一个用逗号分隔的经度和纬度的对),处理器将会从参数中提取其中的经度和纬度值,并使用GetNearbyStoresGML 存储过程返回一个GeoRSS源,它将包含请求搜索点100公里附近的商店。
在Specify the stored procedure name as the command text注释下面,添加下面的代码。
cmd.CommandText = spName

在Create an <entry> element for this row注释下面,添加下面的代码,来为存储过程返回的结果的每行数据创建一个<entry> 标签。
rssOutput.AppendLine("<entry>")

在Use columns 0 and 1 for the title and description注释下面,添加下面的代码来为存储过程返回的数据创建<title> 和<description> 元素。

rssOutput.AppendLine(String.Format("<title>{0}</title>", geomRdr.GetValue(0)))
rssOutput.AppendLine(String.Format("
<description>{0}</description>", _
geomRdr.GetValue(
1)))

在Add a <georss:where> element注释下面,添加下面的代码来为这个GML数据节点创建一个<where> 元素。
rssOutput.AppendLine("<georss:where>")

在Get the geography instance GML from column 2注释下面,添加下面的代码,来从存储过程结果中获取GML数据。
gml = geomRdr.GetValue(2).ToString()

在Add the <gml:> elements to the output XML注释下面,添加下面的代码,来向GeoRSS 源添加GML数据。
rssOutput.AppendLine(gml)

在Close <georss:where> and <entry> elements注释下面,添加下面的代码。
rssOutput.AppendLine("</georss:where>")
rssOutput.AppendLine("</entry>")

在Close the <feed> document and send it as the response注释下面,添加下面的代码来完成GeoRSS 源,并将它发送回请求方。
rssOutput.Append("</feed>")
context.Response.Write(rssOutput.ToString())
保存 GeoRSSHandler.vb。

注册HTTP Handler

在 Solution Explorer中,双击web.config ,在编辑器中打开它。
在<httpHandlers> 节点中,在Register the GeoRSSHandler for .georss requests注释下面,添加下面的XML代码。
<add verb="*" path="*.georss" type="GeoRSSHandler" validate="false"/>
注意: 您必须注册这个HTTP Handlers,用来指定某个特定的文件扩展名,从而让Internet Information Services 可以将这种特定的请求发送给适当的处理器来处理这种文件。
保存 web.config。

添加HTTP Handler

在 Solution Explorer中,点击位于树状图根结点的Web 站点项目文件然后点击F4 查看它的属性。
注意Port number 属性。

在Website 菜单中,点击Start Options。
选择Start URL,输入下面的URL (将<port> 修改为Web站点的Port number 属性),然后点击OK。
http://localhost:<port>/storefindersite/test.georss

在Debug 菜单中,点击Start Debugging。
当 Microsoft Internet Explorer 打开后,查看包含商店名称的RSS源的页面。

在Internet Explorer中,在Web 页面中,右键单击任意位置,然后点击View Source 在Notepad中查看页面的源代码。注意,页面的源是由HTTP Handler所生成的GeoRSS 源。
关闭 Notepad。

在 Internet Explorer中,在地址栏(Address bar)中,在上面的网址后面输入下面的查询字符串,点击键盘上的回车键:
?SearchFrom=34.000000,-118.000000

确认返回的GeoRSS源中包含了一个搜索区域,以及其中的任意商店。
关闭Internet Explorer。
保持Visual Studio 打开,以备下个练习使用。
 

练习 3: 使用Virtual Earth VEMap 控件

在本练习中,您将向页面中添加一些客户端代码,来将从上面的GeoRSS源中获得的地理信息数据显示在Virtual Earth VEMap 控件当中。VEMap 控件是一个客户端控件,您可以使用JavaScript 代码来对它进行编程。使用客户端代码来编辑VEMap控件的优势在于,您可以简单的构建一个mash-up Web 应用程序,它可以与来自于Internet上多种不同数据源的数据进行集成。

添加代码以显示地图

在 Solution Explorer中,双击Default.aspx ,在设计器中打开它进行编辑。
如果它已经被打开,点击设计器左下方的Source 选项卡,从而查看页面的HTML源代码。
在add a reference to the Virtual Earth map control注释下方,添加下面的HTML代码。

<script type="text/javascript"              src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6">
</script>

在GetMap 函数当中,在Display the map control注释下方,添加下面的代码。

map = new VEMap('mapDiv');
map.LoadMap();

保存 Default.aspx。
在Solution Explorer中,右击Default.aspx,然后点击Set as Start Page。
在Debug 菜单中,点击Start Debugging。
当Internet Explorer 打开后,确认地图已经被显示出来。

使用地图中内置的控件来进行移动浏览,放大,缩小,以及更改视图。
关闭Internet Explorer。

添加代码并在地图中显示所有商店

在 Default.aspx中,在ShowAllStores 函数中,在Import GeoRSS feed of store data, and call onAllStoreLoad function when the data is loaded注释下方,添加下面的代码。

var veLayerSpec = new VEShapeSourceSpecification(VEDataType.GeoRSS,
".
/Stores.georss");
map.ImportShapeLayerData(veLayerSpec, onAllStoreLoad, true);

注意: 这段代码将会把Stores.georss页面的请求结果发送到Web页面当中。这个请求将会使用HTTP Handler 进行处理,它使用前面练习中输入的代码来实现,并返回包含所有商店的GeoRSS源。然后,该代码将GeoRSS数据加载为一个新的层,并显示在地图控件当中,并且当数据被成功加载到地图当中后,调用onAllStoreLoad 函数。

在onAllStoreLoad 函数当中,在Count the shapes returned 注释下面,添加下面的代码。

var storecount = feed.GetShapeCount();
document.getElementById("Info").innerHTML
=
'There are ' + storecount + ' stores.';

保存 Default.aspx。
在Debug 菜单中,点击Start Debugging。
在Internet Explorer 打开后,点击Show All Stores ,然后确认所有的商店都被显示在地图中,并用一些“别针”来显示。
关闭Internet Explorer。

添加代码并在地图中显示特定位置附近的商店

在 Default.aspx中,在ShowNearbyStores 函数中,在Use the VEMap.Find method to find the location entered by the user and call the onFind function to process the results注释下方,添加下面的代码。

results  = map.Find( null,
   document.getElementById("SearchLocation").value,
  
null, null,null, 1, false, false, false, true,
   onFind)

注意: 这段代码使用Virtual Earth 来查找一个基于用户输入的文本查找的特定位置。当一个或多个位置被查找到后,代码会调用OnFind 函数。

在onFind 函数当中,在define the search point as the latitude and longitude of the first place in the results注释下面,添加下面的代码。

var SearchFromPoint = places[0].LatLong;

注意: 这段代码处理结果中发现的第一个位置,并将这个用逗号分隔的字符串提取出经度和纬度值。
在onFind 函数当中,在Import GeoRSS feed of stores near the search point, and call onNearbyStoresLoad function when the data is loaded注释下面,添加下面的代码。

var veLayerSpec = new VEShapeSourceSpecification(VEDataType.GeoRSS,
                                ".
/Stores.georss?SearchFrom=" + SearchFromPoint);
map.ImportShapeLayerData(veLayerSpec, onNearbyStoresLoad, true);

注意: 这段代码将发送请求到Stores.georss 页面,并在请求中添加SearchFrom 参数,这个参数中包含了搜索区域的经度和纬度值。这个请求由上面我们实现的HTTP Handler 进行处理,并返回包含搜索区域及其中所有商店位置的GeoRSS源。这段代码的后面将GeoRSS数据加载到到地图控件中,显示为一个新的层,然后在加载完成后调用onNearbyStoresLoad 函数。
在 onNearbyStoresLoad 函数中,在Don't count or show the first shape (the search location)注释下面,添加下面的代码。

var storecount = feed.GetShapeCount()-1;
feed.GetShapeByIndex(
0).HideIcon();
document.getElementById("Info").innerHTML
=
'There are ' + storecount + ' stores.';

在 onNearbyStoresLoad 函数中,在Show the info for the search area when the results first load注释下面,添加下面的代码。

map.ShowInfoBox(feed.GetShapeByIndex(0));

注意: 这段代码显示了搜索区域的信息提示气泡。
保存 Default.aspx。
在Debug 菜单中,点击Start Debugging。
在Internet Explorer 打开后,输入Seattle ,然后点击Show Stores Near ,然后确认所有搜索出来的商店将会在地图上显示为一些别针,并会使用一个圆形显示搜索区域。
重复搜索过程,输入San Francisco 和90210。
关闭Internet Explorer。
关闭Visual Studio。
关闭Virtual PC 并不要保存任何更改。
 

0
相关文章