友情提示,您阅读本篇博文的先决条件如下:
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 Servr 2008空间数据应用系列七:基于Bing Maps(Silverlight) 的空间数据展现》一文中介绍了如何基于Bing Maps呈现SQL Server 2008中存储的空间数据,对于标准的地理空间数据可以通过数据导入的方式将其存放到数据库中(后续文章将详细介绍),对于一些非标准的空间数据或者说是一个软件产品中的业务空间数据,则需要通过人为或其他方式将其存储进数据库,本篇将以如何在Bing Maps(Silverlight)中动态绘制多边图形然后将其存储到SQL Server 2008的空间数据列中为例,详细介绍如何实现自定义图形存储入库的实现方式和原理。
一、创建空间数据表
首先创建空间数据类型字段表,以存储在Bing Maps(Silverlight)中动态绘制的多边形图形数据到空间数据列。
CREATE
TABLE
[
dbo
]
.
[
DrawnPolygons
]
(
[
ID
]
[
int
]
IDENTITY
(
1
,
1
)
NOT
NULL
,
[
Name
]
[
varchar
]
(
50
)
NOT
NULL
,
[
Polygon
]
[
geography
]
NOT
NULL
)
GO
二、编写入库存储过程
目前Linq To Sql和ASP.NET Entity Framework都不支持SQL Server 2008的空间数据类型,前台只能通过字符串或者对象的形式将数据传递到后台服务端,然后通过调用存储过程,在存储过程中对空间数据的字符串进行空间数据对象转换,然后入库。针对上面所创建的空间数据表可以创建如下存储过程来实现多边形空间数据的入库存储。
SET
ANSI_NULLS
ON
GO
SET
QUOTED_IDENTIFIER
ON
GO
CREATE
PROCEDURE
[
dbo
]
.
[
SavePolygon
]
(
@name
varchar
(
50
),
@polytext
varchar
(
max
),
@identity
int
OUTPUT
)
AS
INSERT
INTO
dbo.DrawnPolygons
(Name,Polygon)
VALUES
(
@name
, geography::STPolyFromText(
@polytext
,
4326
))
SET
@identity
=
@@Identity
RETURN
三、编写服务接口
入库接口可以采用WebService或者WCF技术提供,本篇采用WCF作为数据操作接口技术,Linq To Sql做数据访问,自定义方法调用存储过程实现数据库入库操作。
在项目中添加Linq To Sql文件,然后打开对于的代码隐藏文件,在Linq To Sql自动生产的创建数据库连接的代码下面添加如下自定义方法实现数据库存储过程的调用。
[Function(Name
=
"
dbo.SavePolygon
"
)]
public
int
SavePolygon([Parameter(DbType
=
"
VarChar(50)
"
)]
string
name,
[Parameter(DbType
=
"
VarChar(MAX)
"
)]
string
polygontext,
[Parameter(DbType
=
"
Int
"
)]
ref
System.Nullable
<
int
>
identity)
{
IExecuteResult result
=
this
.ExecuteMethodCall(
this
, ((MethodInfo)(MethodInfo.GetCurrentMethod())), name, polygontext, identity);
identity
=
((System.Nullable
<
int
>
)(result.GetParameterValue(
2
)));
return
((
int
)(result.ReturnValue));
}
如上实现了Linq To Sql对存储过程的调用,接下来就是创建WCF服务提供给Silverlight调用。
[ServiceContract]
public
interface
IDrawService
{
///
<summary>
///
保存多边形对象到空间数据库
///
</summary>
///
<param name="name"></param>
///
<param name="arrayOfLatLong"></param>
///
<returns></returns>
[OperationContract]
int
?
SavePolygon(
string
name, List
<
MapPoint
>
arrayOfLatLong);
}
在WCF服务的详细实现中将Bing Maps客户端传递过来的参数构造为空间数据类型的WKT文本格式,通过上面的存储过程就可以直接将WKT转化为空间数据类型直接入库。
public
class
DrawService : IDrawService
{
public
int
?
SavePolygon(
string
name, List
<
MapPoint
>
arrayOfLatLong)
{
var sb
=
new
StringBuilder();
sb.Append(
"
POLYGON ((
"
);
for
(var i
=
arrayOfLatLong.Count; i
>=
1
; i
--
)
{
var j
=
i
-
1
;
sb.Append(arrayOfLatLong[j].Longitude.ToString());
sb.Append(
"
"
);
sb.Append(arrayOfLatLong[j].Latitude.ToString());
sb.Append(
"
,
"
);
}
sb.Remove(sb.Length
-
1
,
1
);
sb.Append(
"
))
"
);
int
?
identity
=
0
;
var connectionString
=
ConfigurationManager.ConnectionStrings[
"
Sql08ConnectionString
"
].ConnectionString;
BMPTSDataContext ctx
=
new
BMPTSDataContext(connectionString);
ctx.SavePolygon(
"
西南大区
"
, sb.ToString(),
ref
identity);
return
identity;
}
}
接口中使用的数据传输对象MapPoint的详细定义如下代码块:
///
<summary>
///
地图坐标点(经度,纬度)
///
</summary>
[DataContract]
public
class
MapPoint
{
[DataMember]
public
double
Latitude {
get
;
set
; }
[DataMember]
public
double
Longitude {
get
;
set
; }
public
MapPoint() { }
public
MapPoint(
double
lat,
double
lng)
{
this
.Latitude
=
lat;
this
.Longitude
=
lng;
}
}
四、Bing Maps客户端的实现
客户端的实现非常简单,首先创建Silverlight应用程序并添加Bing Maps Silverlight Control开发组件的引用,其次在界面中添加Map对象以显示Bing Maps原型界面,最后可以设计一个小的工具面板,以按钮的方式驱动触发绘制多边形的行为,以及保存图形到数据库的命令请求。如下界面效果:

对于绘制多边形的算法这里鉴于篇幅限制就不一一贴出来了,详细可通过文末提供的代码下载链接下载本文的示例代码。比如限制绘制一个【成都-重庆-贵阳-昆明】这四个城市组成的西南大区多变型图形,并将其图形数据以空间数据的形式存储到SQL Server 2008中。图形如下图所示:

通过点击“保存数据”按钮则将地图界面绘制的图形数据取出来构造为数组传递到WCF服务接口,调用数据库存储过程实现数据入库操作,下面是保存按钮的代码实现。
private
void
btnSave_Click(
object
sender, RoutedEventArgs e)
{
LocationCollection lc
=
this
._drawLine.Locations;
ObservableCollection
<
MapPoint
>
polygon
=
new
ObservableCollection
<
MapPoint
>
();
for
(
int
i
=
0
; i
<
lc.Count; i
++
)
{
polygon.Add(
new
MapPoint { Longitude
=
lc[i].Longitude, Latitude
=
lc[i].Latitude });
}
//
调用WCF接口实现数据入库
DrawServiceClient client
=
new
DrawServiceClient();
client.SavePolygonAsync(
this
.tbName.Text.Trim(), polygon);
client.SavePolygonCompleted
+=
client_SavePolygonCompleted;
}
private
void
client_SavePolygonCompleted(
object
sender, SavePolygonCompletedEventArgs e)
{
if
(e.Error
!=
null
)
{
this
.tbResult.Text
=
e.Result.Value
>
0
?
"
保存成功!
"
:
"
保存失败
"
;
}
}
五、数据库中的空间数据
当通过Bing Maps中动态绘制多边形图形对象,然后将图形数据通过WCF服务接口入库保存后,可以通过SQL Server Management Studio查询并在空间数据结果中直接预览结果。
SELECT
[
ID
]
,
[
Name
]
,
[
Polygon
]
FROM
[
dbo
]
.
[
DrawnPolygons
]

六、相关资料
[1]、Geography数据类型:http://msdn.microsoft.com/zh-cn/library/cc280766.aspx
[2]、地域实例上的OGC方法:http://msdn.microsoft.com/zh-cn/library/bb933917.aspx
[3]、地理实例上的扩展方法:http://msdn.microsoft.com/zh-cn/library/bb933968.aspx
[4]、OGC静态地理方法:http://msdn.microsoft.com/zh-cn/library/bb933988.aspx
[5]、扩展静态地理方法:http://msdn.microsoft.com/zh-cn/library/bb933921.aspx
七、示例代码下载
