友情提示,您阅读本篇博文的先决条件如下:
1、本文示例基于Microsoft SQL Server 2008 R2调测。
2、具备 Transact-SQL 编程经验和使用 SQL Server Management Studio 的经验。
3、具有使用 Microsoft Visual Studio 进行 Microsoft .NET Framework开发的经验。
4、具有使用WCF、Silverlight、ADO.NET开发的经验。
5、熟悉或了解Microsoft SQL Server 2008中的空间数据类型。
6、具备相应(比如OGC)的GIS专业理论知识。
SQL Server 2008中存储的空间数据,除了能够直接基于SQL Server做空间查询、空间分析外,由于SQLCLR提供了非常丰富、完善的开发API,使得空间数据可以在不同的常用空间数据类型之间转换,同时还可以非常简单的和地图应用无缝集成使用。本篇博文以Bing Maps Silverlight Control为地图应用客户端为基础,介绍如何实现在Bing Maps中呈现地理空间数据。
一、准备空间数据
为了演示如何基于Bing Maps Silverlight Control来呈现SQL Server 2008中存储的空间数据,首先需要在数据库中模拟一些数据供数据查询使用,随意创建一个带有空间数据类型字段的表就可以,如下SQL脚本。
CREATE
TABLE
DrawnPolygons(
[
ID
]
[
int
]
IDENTITY
(
1
,
1
)
NOT
NULL
,
[
Name
]
[
varchar
]
(
50
)
NOT
NULL
,
[
Polygon
]
[
geography
]
NOT
NULL
)
GO
对于上面脚本所创建的表格,随意的构造几条数据,如下图SQL Server Management Studio的空间结果中所呈现的效果。

二、编写数据服务接口
数据结构使用WebService或者WCF提供都可以,本篇选用WCF Service提供地图数据访问接口,实现将数据库的空间数据读取出来返回到Bing Maps的地图客户端。由于目前的Linq To Sql和ASP.NET Entity Framewrok还不支持SQL Server 2008的空间数据类型,数据访问只能自己编写ADO.NET实现。如下代码块:
private
DataTable Query(
string
sql)
{
string
cstring
=
ConfigurationManager.ConnectionStrings[
"
BingMapsDB
"
].ConnectionString;
SqlConnection conn
=
new
SqlConnection(cstring);
if
(conn.State
==
ConnectionState.Closed) conn.Open();
SqlDataAdapter adapter
=
new
SqlDataAdapter(sql, conn);
DataSet ds
=
new
DataSet();
adapter.Fill(ds);
return
ds.Tables[
0
];
}
直接在WCF中对外公布一个公共方法,并将其标记为操作契约(OperationContract)就完成了服务接口的提供,该接口实现数据库查询并将数据库数据数据组合为对象集合返回到客户端,详细实现如下代码块。
[OperationContract]
public
List
<
DrawnPolygons
>
QueryPolygons()
{
var sql
=
"
SELECT * FROM [DrawnPolygons]
"
;
var result
=
Query(sql);
List
<
DrawnPolygons
>
areas
=
null
;
if
(result
!=
null
&&
result.Rows.Count
>
0
)
{
areas
=
new
List
<
DrawnPolygons
>
();
foreach
(DataRow row
in
result.Rows)
{
areas.Add(
new
DrawnPolygons
{
ID
=
int
.Parse(row[
"
ID
"
].ToString()),
Name
=
row[
"
NAME
"
].ToString(),
Xaml
= ToXaml(row["Polygon"], row["ID"
].ToString())
});
}
}
return
areas;
}
接口使用了数据传输对象DrawnPolygons,其他结构如下定义:
[DataContract]
public
class
DrawnPolygons
{
[DataMember]
public
int
ID {
get
;
set
; }
[DataMember]
public
string
Name {
get
;
set
; }
[DataMember]
public
string
Xaml {
get
;
set
; }
}
三、构造空间数据客户端对象
在这里请大家讲视眼转移到本篇前面代码片段的中加粗大红字体处,会发现使用了一个名为“ToXaml()”的方法,此方法的主要功能就是实现将空间数据转换为客户端Silverlight能够识别的xaml语言标记。该方法的详细实现如下代码块所示:
private
string
ToXaml(
object
polygon,
string
id)
{
StringBuilder sb
=
new
StringBuilder();
//
将数据库查询出的空间数据构造为SQL Server空间数据类型对象
var geo
=
SqlGeography.STGeomFromText(
new
SqlChars(
new
SqlString(polygon.ToString())),
4326
);
//
将空间数据构造为Bing Maps图形(多边形)对象的Xaml文本,以返回到客户端直接解析Xaml为Silverlight程序中的对象。
for
(
int
j
=
1
; j
<=
geo.NumRings(); j
++
)
{
if
(geo.RingN(j).STNumPoints()
>
1
)
{
sb.Append(
"
<m:MapPolygon xmlns:m=\"clr-namespace:Microsoft.Maps.MapControl;assembly=Microsoft.Maps.MapControl\"
"
);
sb.Append(
"
Fill=\"Red\" Locations=\"
"
);
for
(
int
k
=
1
; k
<=
geo.RingN(j).STNumPoints(); k
++
)
{
if
(k
>
1
) sb.Append(
"
"
);
sb.Append(String.Format(
"
{0:0.#####},{1:0.#####}
"
,
(
double
)geo.RingN(j).STPointN(k).Lat,
(
double
)geo.RingN(j).STPointN(k).Long));
}
sb.AppendLine(
"
\"/>
"
);
}
}
return
sb.ToString();
}
实际上,在服务端将空间数据转化为Xaml并非实现传递空间数据到客户端并解析呈现到GIS界面的唯一选择,还可以将数据库空间数据处理为KML、GML等常用的其它能够表示存储地图数据的任意格式返回到客户端使用。这里为何选择将空间数据解析为Xaml语言标记的目的是为了Silverlight能够直接将Xaml语言标记解析为对应的对象,并能够直接使用。如果选择将空间数据解析为别的地图数据格式,还需要额外的解析算法去实现空间数据的解析。
四、Bing Maps客户端的实现
Bing Maps Silverlight客户端只需要调用上面提供的WCF Service接口,将空间数据查询到客户端,然后通过XamlReader的接口解析Xaml为对应的对象即可,可以在应用程序加载时就发起对接口的调用。如下代码块所示:
public
MainPage()
{
InitializeComponent();
//
调用WCF服务接口查询空间数据到客户端
DataServiceClient service
=
new
DataServiceClient();
service.QueryPolygonsCompleted
+=
new
EventHandler
<
QueryPolygonsCompletedEventArgs
>
(service_QueryPolygonsCompleted);
service.QueryPolygonsAsync();
}
private
void
service_QueryPolygonsCompleted(
object
sender, QueryPolygonsCompletedEventArgs e)
{
if
(e.Error
!=
null
)
return
;
for
(
int
i
=
0
; i
<
e.Result.Count; i
++
)
{
//
将空间数据所构造的Xaml语言标记解析为Bing Maps Silverlight Control中的多边形(MapPolygon)对象。
MapPolygon polygon
=
(MapPolygon)XamlReader.Load(e.Result[i].Xaml);
//
将多边形对象添加到地图中呈现。
map.Children.Add(polygon);
}
}

四、相关资料
[1]、数据表中使用空间数据类型:http://www.cnblogs.com/beniao/archive/2011/02/21/1959347.html
[2]、几何实例上的OGC方法:http://msdn.microsoft.com/zh-cn/visualc/bb933960.aspx
[3]、几何图形实例上的扩展方法:http://msdn.microsoft.com/zh-cn/library/bb933880.aspx
[4]、OGC 静态几何图形方法:http://msdn.microsoft.com/zh-cn/library/bb933894.aspx
[5]、Bing Maps开发系列博文:http://www.cnblogs.com/beniao/archive/2010/01/13/1646446.html