[原文作者]: Beth Massi
[原文链接]: Northwind Meets Virtual Earth – Generate VE Maps with LINQ
利用VB9和Linq,你可以很容易地从多个数据源之间创建XML文件,这些数据源包括关系型数据、 XML文件和其它任何可查询对象,因为绝大多数流行的系统之间的交互都是以XML的格式进行的,所以应用是很广泛的。在VB9中SOAP,XAML,HTML,RSS都能够很容易地通过Linq To XML创建。比如, 如果我们想在一个VE生成的地图中显示所有Northwind库中的Customers信息,我们需要怎么做?
VE允许我们传递给它一个RSS文档,文档里面的每个item指定了纬度和经度以便能够绘制出他们在地球上的每个位置;这里有两种不同的格式可以传递,其中之一就是GeoRSS标准,我们需要做的就是通过获取customers表中包含的地址信息中的经纬度来创建这个XML,并且将这个GeoRSS传递给虚拟地球;我们可以利用http://geocoder.us 中的服务来获取在美国的Customers的经纬度信息,这个服务能够从许多格式的美国地址(包括Restful RDF)中返回一组对应的经纬度信息,为了从Northwind中的customers表中创建GeoRss,我们可以在Linq查询中使用这个服务。
假设我们在Server Explorer中已经有一个到Northwind库的连接(或者其它的含有地址的数据库也可以),首先添加一个“LINQ TO SQL classes”到你的项目中,将它命名为Northwind.dbml ,并且将Customers表从Server Explorer中拖拉到设计器中,下一步就是在代码文件的头部引入Geo命名空间,因为geo命名空间的http://geocoder.us 服务将返回XML文件,我们将使用到XML文件里的地址信息。
Imports <xmlns:geo=“http://www.w3.org/2003/01/geo/wgs84_pos#“>
现在我们可以写一个查询来为customers创建GeoRSS,因为Northwind库中包含的地址绝大多数是编造的,你可以将这些地址改成真实的,或者我们可以选择居住在Oregon (OR)的Customers,因为那有一些有效的地址。
Dim db As New NorthwindDataContext
Dim geoRSS = _
<rss xmlns:geo=“http://www.w3.org/2003/01/geo/wgs84_pos#“>
<channel>
<title>Northwind Customer Locations</title>
<link></link>
<%= From Customer In db.Customers _
Let Desc = Customer.Address & “, “ & Customer.City _
Let Address = Customer.Address & “,” & Customer.PostalCode _
Where Customer.Country = “USA” AndAlso Customer.Region = “OR” _
Select <item>
<title><%= Customer.ContactName %></title>
<description><%= Desc %></description>
<%= GetGeoCode(Address).Descendants %>
</item> %>
</channel>
</rss>
在这个查询中我们建立了GeoRSS并且调用了一个使用者,里面定义了函数GetGeoCode,该函数接受customer的地址参数,返回它的经纬度;注意,我们在查询中使用了Let关键字,目的是为description和address创建查询变量,这些变量在下面建立<item>时将会使用到。如果有结果,函数GetGeoCode将返回一个包含位置信息的XElement,XElement的子方法在查询中被回调,为的是在GeoRSS中安放<geo:lat> 和 <geo:long>节点。
Function GetGeoCode(ByVal address As String) As XElement
Dim url = “http://geocoder.us/service/rest/?address=” & Server.UrlEncode(address)
Try
Dim geo = XElement.Load(url)
Return <location>
<%= geo.<geo:Point>.<geo:long> %>
<%= geo.<geo:Point>.<geo:lat> %>
</location>
Catch ex As Exception
Return <location></location>
End Try
End Function
现在我们已经拥有了GeoRSS,可以将它传递给虚拟地球,以利用它来创建地图。例如,我们可以仅仅创建一个简单的ASP.net应用,并且将创建好的GeoRSS保存到一个Session变量中。默认页面需要有JavaScript代码,我们将利用它把GeoRSS传递到虚拟地球,并且发送一个ID为”mymap”的<div>块,块中定义了在页面上安放地图的区域。(想了解更多的API信息,可以看一下虚拟地球文档)
<%@ Page Language=”vb” AutoEventWireup=”false”
CodeBehind=”Default.aspx.vb” Inherits=”NorthwindVirtualEarth._Default” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head runat=”server”>
<title>Northwind Customers on Virtual Earth</title>
<link href=”style.css” rel=”stylesheet” type=”text/css” />
<script type=”text/javascript”
src=”http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=5″>
</script>
<script type=”text/javascript”>
var map = null;
var layerid=1;
function GetMap()
{
map = new VEMap(‘myMap’);
map.LoadMap();
var l = new VEShapeLayer();
var veLayerSpec = new VEShapeSourceSpecification(VEDataType.GeoRSS, “georss.aspx”, l);
map.ImportShapeLayerData(veLayerSpec, null);
}
</script>
</head>
<body id=”body” runat=”server” >
<form id=”form1″ runat=”server”>
<h1>Northwind Customers on Virtual Earth</h1>
<div id=’myMap’ style=”position: relative; width: 800px; height: 400px;”>
<asp:Label ID=”lblStatus” runat=”server” Text=”No items found” Visible=”False”></asp:Label>
</div>
</form>
</body>
</html>
Default.aspx的VB后台代码只是简单地做了检查,看看是否有任何从geoRSS查询中返回的<item>元素,如果有,则动态地在body的onload事件里添加调用GetMap的javascript函数代码。
If geoRSS…<item>.Count > 0 Then
Session(“georss”) = geoRSS
Me.body.Attributes.Add(“onload”, String.Format(“GetMap()”))
Else
Me.lblStatus.Visible = True
Session(“georss”) = <rss></rss>
End If
另外一个页面是GeoRss.aspx,是一个空白页,仅仅返回存储在session变量中的GeoRSS,正是javascript方法需要调用的内容。
Public Partial Class GeoRSS
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim georss As XElement = CType(Session(“georss”), XElement)
Response.ContentType = “text/xml”
Response.Write(georss.ToString())
End Sub
End Class
这里关键的地方在于一个Linq查询语句中跨越了多个数据源(Northwind库和geocoder.us服务),而且只创建了一个单一的XML文档,它符合GeoRSS标准,将它传递到虚拟地球,用来产生我们的地图。正如你在这个RSS示例中所看到的,利用Linq和VB9从多数据源中创建XML是非常简单地一件事。代码附件
如果你对利用WPF和你的数据创建动态地图感兴趣,不要忘记参阅Wisniewski的DevCenter featured 中的文章 Create Dynamic Maps with Visual Basic 9.0 and WPF.
