Edit this page

SQL Geospatial Data

Since Q2 2011 a new class - RadGeospatialDataReader was added to support binding RadMap to SQL Geospatial data. It allows generating map shapes from any IEnumerable instance (for example a row collection) which contains a property with geospatial data in Wkt (Well known text) or Wkb (Well known binary) format. The Source property and the GeospatialPropertyName property are used to specify the IEnumerable instance and the name of the property which contains a Geospatial data.

The SqlGeospatialDataReader supports the following geometry types:

  • Point

  • LineString

  • Polygon

  • Triangle

  • MultiPoint

  • MultiLineString

  • MultiPolygon

  • GeometryCollection

The coordinates for geometries may be 2D (x, y), 3D (x, y, z), 4D (x, y, z, m) with an m value that is part of a linear referencing system or 2D with an m value (x, y, m). However the SqlGeospatialDataReader uses the x and y coordinates only, so that the z and m coordinates will be ignored. The SqlGeospatialDataReader can be used in the InformationLayer.Reader property the same way as the MapShapeReader. The sample code is below:

<telerik:InformationLayer x:Name="informationLayer">
    <telerik:InformationLayer.Reader>
        <telerik:SqlGeospatialDataReader x:Name="sqlGeospatialDataReader" 
                   ExtendedPropertySet="Area,string Latitude,double Longitude,double"
                   Source="{Binding Source={StaticResource domainServiceContext}, Path=LocationsWKTs}"
                   GeospatialPropertyName="Point" ToolTipFormat="Area" PreviewReadCompleted="reader_PreviewReadCompleted" />
    </telerik:InformationLayer.Reader>
</telerik:InformationLayer>

It allows using the ClearLayer, ExtendedPropertySet, ToolTipFormat, ToolTipTemplate, ToolTipStyle and CoordinateConverter properties the same way they are used in MapShapeReader. Also it supports the PreviewReadCompleted and ReadCompleted events which are used in MapShapeReader.

The SqlGeospatialDataReader class allows using the following data sources:

  • Domain Service

  • Wcf Data Service

  • ADO.NET Entity Data Model

  • Linq to SQL

  • DataSet

  • Telerik OpenAccess Domain Model

Also the SqlGeospatialDataReader can use any custom data class which implements the IEnumerable interface and contains a property with geospatial data in Wkt (Well known text) or Wkb (Well known binary) format. In this case the geospatial property should be a string, byte array or any other type which allows to get geospatial data in Wkt using the ToString() method. Note, the data models in Visual Studio 2010 (except the Telerik OpenAccess Domain Model) do not allow to use native SQL geospatial field types. You will need to create for example appropriate views on the SQL server which converts the native geospatial field to WKT or WKB formatted field. It could be done using the STAsText and STAsBinary stored procedures. A sample view definition is shown:

SQL

SELECT        id, Area, Latitude, Longitude, GeoLocation.STAsBinary() AS Point
FROM            dbo.Locations

<Window x:Class="EntityDataModelTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"&#13;        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&#13;        xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"&#13;        xmlns:local="clr-namespace:EntityDataModelTest"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:Database1Entities x:Key="dataBase" />
    </Window.Resources>
    <Grid x:Name="LayoutRoot">
        <telerik:RadMap x:Name="radMap"
            Center="40,-100"
            ZoomLevel="3">
            <telerik:RadMap.Provider>
                <telerik:OpenStreetMapProvider />
            </telerik:RadMap.Provider>
            <telerik:InformationLayer x:Name="informationLayer">
                <telerik:InformationLayer.Reader>
                    <telerik:SqlGeospatialDataReader x:Name="sqlGeospatialDataReader" 
                                         GeospatialPropertyName="Point"
                                         Source="{Binding Source={StaticResource dataBase}, Path=LocationsWKB}"
                                         ToolTipFormat="{}{Area} ({Latitude} : {Longitude})"
                                         PreviewReadCompleted="reader_PreviewReadCompleted" />
                </telerik:InformationLayer.Reader>
            </telerik:InformationLayer>
        </telerik:RadMap>
    </Grid>
</Window>

If you use Wcf Data Service or Domain Service in your Silverlight application, then their instances cannot be used directly to get the geospatial table data for the SqlGeospatialDataReader. Source property. In this case the geospatial data is retrieved asynchronously. So, you should use the Completed event to set the SqlGeospatialDataReader.Source. It will be useful to use the small proxy class like to the following sample class for Domain Service:

public class DomainServiceContext : INotifyPropertyChanged
{
  private DomainService1 domainService1Context = new DomainService1();
  private IEnumerable locationsWKTs;
  public new IEnumerable LocationsWKTs
  {
   get
  {
    if (this.locationsWKTs == null)
  {
    var loadOp = this.domainService1Context.Load(this.domainService1Context.GetLocationsWKTsQuery());
    loadOp.Completed += new EventHandler(loadOp_Completed);
  }
return this.locationsWKTs;
}
 set
  {
   this.locationsWKTs = value;
   this.OnPropertyChanged("LocationsWKTs");
   }
} 
private void loadOp_Completed(object sender, EventArgs e)
   {
    var loadOp = sender as LoadOperation;
    if (loadOp != null)
     {
      this.LocationsWKTs = loadOp.Entities;
     }
  }

 public event PropertyChangedEventHandler PropertyChanged;

private void OnPropertyChanged(string name)
 {
   PropertyChangedEventHandler handler = PropertyChanged;
  if (handler != null)
   {
     handler(this, new PropertyChangedEventArgs(name));
    }
  }
}
Public Class DataBaseContext
      Inherits Database1Entities1
      Implements INotifyPropertyChanged
    Public Sub New()
          MyBase.New(New Uri("http://localhost:6838/WcfDataService1.svc"))
    End Sub
    Private locationsWKBs_Renamed As IEnumerable
    Public Shadows Property LocationsWKBs() As IEnumerable
          Get
                If Me.locationsWKBs_Renamed Is Nothing Then
                      Dim query = MyBase.LocationsWKBs
                      Me.RunDataServiceQuery(query)
                End If

                Return Me.locationsWKBs_Renamed
          End Get

          Set(ByVal value As IEnumerable)
                Me.locationsWKBs_Renamed = value
                Me.OnPropertyChanged("LocationsWKBs")
          End Set
    End Property

    Public Sub RunDataServiceQuery(Of T)(ByVal query As IQueryable(Of T))
          Dim entity = New DataServiceCollection(Of T)()

          AddHandler entity.LoadCompleted, AddressOf entity_LoadCompleted
          entity.LoadAsync(query)
    End Sub

    Private Sub entity_LoadCompleted(ByVal sender As Object, ByVal e As LoadCompletedEventArgs)
          Me.LocationsWKBs = TryCast(sender, IEnumerable)
    End Sub

    Public Event PropertyChanged As PropertyChangedEventHandler

    Private Sub OnPropertyChanged(ByVal name As String)
          Dim handler As PropertyChangedEventHandler = PropertyChangedEvent
          If handler IsNot Nothing Then
                handler(Me, New PropertyChangedEventArgs(name))
          End If
    End Sub
End Class

You may review our demo with source code - Wkt Reader that loads the sample data from collection of Wkt based data.

Was this article helpful? Yes No

Give article feedback

Tell us how we can improve this article

Dummy