重温欧几里得几何
如果你上数学课时没有打瞌睡,你一定会回忆得起欧几里得几何和最简单的直角坐标系,如图3所示,在这个坐标系中,起点的坐标是(0,0),x轴是从左往右递增,y轴是从下向上递增,无论使用哪种单位,计算出来的距离都是一样的。

图 3 经典的直角坐标系
SQL Server的geometry数据类型在这种模型下可以工作得很好,SQL Server内部将其当作.Net类型,因此你可以在应用程序中直接使用相同的类型,这个类型定义在Microsoft.SqlServer.Types.dll中,这个动态库默认位于C:\Program Files\Microsoft SQL Server\100\SDK\Assemblies。
如果你想将这些数据类型真正用起来,看看图4的例子就会有一点感觉,这个示例程序很简单,上面是数据库中存储的数值,下面是在地图上对这些点位的标注,此外,它可以检查一个点是否在某个多边形范围内。

图 4 示例应用程序
按下最顶端的按钮,它可以将一个几何点保存到数据库中,为了存储这些数据,首先需要创建表:
[ID] [int] IDENTITY(1,1) NOT NULL,
[Points] [geometry] NOT NULL,
[Description] [nvarchar](50) NULL
)
有了这个表,你就可以使用下面的C#代码将值存储到该字段中了:
...
private void geometryAddPointButton_Click(
object sender, EventArgs e)
{
int x = int.Parse(geometryXTextBox.Text);
int y = int.Parse(geometryYTextBox.Text);
SqlGeometry geom = SqlGeometry.Point(x, y, 0);
// add to database
string sql = "INSERT INTO [geometrytest] " +
"([points], [description]) VALUES " +
"(@points, @description)";
StorePointIntoDatabase(geom, sql, "geometry",
"My first geometry point");
}
首先,代码从用户界面读取x和y坐标,然后利用x和y值构造一个SqlGeometry实例,SqlGeometry类型位于Microsoft.SqlServer.Types命名空间中,那么如何使用类的Point方法构造一个点对象呢,最后一步,构造一个SQL insert语句,真正的数据库访问由StorePointIntoDatabase方法完成,而它又是这样实现的:
object geoPoint, string sql,
string udtTypeName, string description)
{
SqlConnection conn = GetConnection();
try
{
SqlCommand cmd = new SqlCommand(
sql, conn);
SqlParameter param = cmd.Parameters.
AddWithValue("@points", geoPoint);
param.UdtTypeName = udtTypeName;
cmd.Parameters.AddWithValue(
"@description", description);
conn.Open();
int rows = cmd.ExecuteNonQuery();
MessageBox.Show("Added " + rows +
" row(s) to the database.");
cmd.Dispose();
return rows;
}
finally
{
conn.Dispose();
}
}
如果你之前曾经使用过SQL Server,上面的代码你应该很熟悉。首先,打开一个SQL Server数据库连接(关于打开数据库连接的细节在这里并不重要),然后使用给定的insert语句构造一个SqlCommand对象。
注意Parameters.AddWithValue调用是如何指定参数值的,在其它大多数参数类型中,单独调用AddWithValue就足够了,但新的地理空间类型是当作UDF类型(.Net类型)的,参数对象的UdtTypeName属性必需设置,对于geometry类型,它设为geometry,对于geography类型就设为geography。
现在你应该知道空间数据是如何添加到SQL Server 2008的数据库表中的了,现在你需要知道如何从这些表中读取空间数据,假设你的数据库表名是GeometryTest,这个表有一个id值,你可能需要根据给定的id值进行检索,在程序代码,可能需要实现下面的代码:
{
SqlConnection conn = GetConnection();
try
{
string sql = "SELECT [points] " +
"FROM [geometrytest] " +
"WHERE ([id] = @id)";
SqlCommand cmd = new SqlCommand(
sql, conn);
cmd.Parameters.AddWithValue("@id", id);
conn.Open();
object geometryPoint = cmd.ExecuteScalar();
if ((geometryPoint != null) &&
(geometryPoint is SqlGeometry)) {
return (SqlGeometry)geometryPoint;
}
else return null;
}
finally
{
conn.Dispose();
}
}
这里实现得非常简单,你只需要一个SQL Server连接,一个命令对象和一条简单的SQL语句,然后你就可以设定参数值读取结果。