Using NHibernate Spatial

NHibernate Spatial brings the spatial capabilities of several relational databases to the NHibernate API. In this recipe, we'll show you how to use NHibernate Spatial with Microsoft SQL Server 2014 to query for a geographic region containing a point.

Getting ready

In SQL Server 2014 Express, create a new, blank database named Spatial.

Download State shapes from the US Census website by following these steps:

  1. Inside the solution directory, create a directory named SpatialData.
  2. Download the Shape file containing all 50 states, D.C., and Puerto Rico from the United States Census website at https://www.census.gov/geo/maps-data/data/cbf/cbf_counties.html or from the code download for this book. The file is named st99_d00_shp.zip.
  3. Extract all three files to the SpatialData folder. The files are named st99_d00.shp, st99_d00.dbf, and st99_d00.shx.

Import the data from the Shapefile into the Spatial database using the following steps:

  1. Inside the solution directory, create a directory named SpatialTools.
  2. Download the SQL Spatial tools from the SharpGIS website at http://www.sharpgis.net/page/SQL-Server-2008-Spatial-Tools.aspx.
  3. Extract the files to the SpatialTools folder.
  4. Run Shape2SQL.exe from the SpatialTools folder.
  5. When prompted, enter your database information as shown in the next screenshot, and click OK:
    Getting ready
  6. Click on the ellipses next to the Shapefile textbox to browse for the Shapefile. Select the co99_d00.shp Shapefile we downloaded and extracted in the SpatialData folder.
  7. Check the Set SRID checkbox, and enter 4269 as the SRID.
  8. Change the table name to StatePart, as shown in the next screenshot:
    Getting ready
  9. Click on Upload to Database.
  10. When the upload process is complete, close the Shape2SQL tool.

Test your imported data using the following steps:

  1. Open the Spatial database in Microsoft SQL Server Management Studio 2014.
  2. Run the following query:
    SELECT * FROM StatePart WHERE Name LIKE 'Texas'
    
  3. The Results tab should contain two rows.
  4. The Spatialresults tab should display the following image:
    Getting ready

How to do it…

  1. Create a new, empty class library project named Eg.Spatial.
  2. Install the GeoAPI package using NuGet Package Manager Console by executing the following command:
    Install-Package GeoAPI
    
  3. Create a class named StatePart with the following code:
    public class StatePart
    {
    
      public virtual int Id { get; protected set; }
      public virtual string Name { get; protected set; }
      public virtual float Area { get; protected set; }
      public virtual float Perimeter { get; protected set; }
      public virtual IGeometry Geometry { get; protected set; }
    
    }
  4. Create an embedded resource mapping file for StatePart with the following XML:
    <?xml version="1.0" encoding="utf-8" ?>
     <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
       assembly="Eg.Spatial"
       namespace="Eg.Spatial">
      <typedef name="Geometry"
        class="NHibernate.Spatial.Type.GeometryType, 
        NHibernate.Spatial">
        <param name="srid">4269</param>
        <param name="subtype">GEOMETRY</param>
      </typedef>
      <class name="StatePart"
        table="StatePart"
        mutable="false"
        schema-action="none">
          <id name="Id" column="ID">
          <generator class="assigned" />
          </id>
        <property name="Name" column="NAME"/>
        <property name="Area" column="AREA"/>
        <property name="Perimeter" column="PERIMETER"/>
        <property name="Geometry" type="Geometry"
         column="geom" />
      </class>
     </hibernate-mapping>
  5. Create a new console project named Eg.Spatial.Runner.
  6. Add references to the Eg.Spatial model.
  7. Install the NHibernate, NHibernate Spatial Form Microsoft SQL Server, and log4net packages using NuGet Package Manager console by executing the following commands:
    Install-Package NHibernate 
    Install-Package NHibernate.Spatial.MsSql
    Install-Package log4net
    
  8. Add an App.config file with standard log4net and hibernate-configuration sections as implemented in Chapter 1, The Configuration and Schema.
  9. Change the connection string to point to the Spatial database, as shown in the following code:
    <connectionStrings>
      <add name="db" connectionString="Server=.SQLExpress; Database=Spatial; Trusted_Connection=SSPI"/>
    </connectionStrings>
  10. Change the NHibernate dialect property to the MsSql2012GeometryDialect:
    <property name="dialect">
      NHibernate.Spatial.Dialect.MsSql2012GeometryDialect, NHibernate.Spatial.MsSql
    </property>
  11. Use the following code in the Main method of Program.cs:
    static void Main()
    {
    
      XmlConfigurator.Configure();
      var log = LogManager.GetLogger(typeof (Program));
    
      var cfg = new Configuration().Configure();
    
      cfg.AddAuxiliaryDatabaseObject(
        new SpatialAuxiliaryDatabaseObject(cfg));
    
      var sessionFactory = cfg.BuildSessionFactory();
    
      //Houston, TX 
      var houstonTX = new Point(-95.383056, 29.762778);
    
      using (var session = sessionFactory.OpenSession())
      {
        using (var tx = session.BeginTransaction())
        {
            var query = session.QueryOver<StatePart>()
            .WhereSpatialRestrictionOn(x => x.Geometry)
            .Contains(houstonTX);
          var part = query.SingleOrDefault();
          if (part == null)
          {
            log.InfoFormat("Houston, we have a problem.");
          }
          else
          {
            log.InfoFormat("Houston is in {0}", part.Name);
          }
          tx.Commit();
        }
      }
    
    }
  12. Build and run the program.
  13. Check the log output for the line Houston is in Texas.

How it works…

In this recipe, we have simply created a Point with the latitude and longitude of Houston, Texas. Then we created an NHibernate criterion query to find the geometries containing that point. The geom field in each row of our StateParts table has a single polygon representing some distinct landmass. For example, Texas has two rows. The first polygon defines the border of mainland Texas while the other represents Padre Island, the large barrier island that runs along the South Texas shore. When our query returns the StatePart entity that contains our point, we output the Name field.

To allow for the additional spatial-related SQL keywords and syntax, we use the MsSql2012GeometryDialect.

The Geometry property on our StatePart entity is an IGeometry. This is mapped using the user type GeometryType. We also provide the Spatial Reference Identifier (SRID), for our datum, and a subtype as parameters for this user type. Datums and SRIDs are explained later in this recipe.

There's more…

This recipe barely scratches the surface of what is possible with NHibernate Spatial. With just basic spatial data, it's possible to query for any number and combination of criteria, from the availability of valuable natural resources to the standard find the nearest retail location feature on a website.

Geography or geometry?

To rephrase this question differently, should you use a globe or map? Geography corresponds to the round-earth model, much like a globe. It works well for making measurements over great distances, accounting for the curvature of the earth.

Geometry, on the other hand, corresponds with the planar system or flat-earth model, like a map. As with a map, some distortion is tolerated, and this system is best-suited for smaller regions. However, standards for full-featured geometry data types are well established, while standards for geography data types are generally lacking. NHibernate Spatial has full support for geometry, as well as limited support for geography.

What's this SRID?

A datum is a model of the shape of the earth, combined with defined points on the surface used to measure accurate latitude and longitude. It's a sort of calibration where an exact location is defined in the datum as being at a precise latitude and longitude, and then everything else is measured from that point. For example, the North American Datum of 1927 (NAD 27) defines a marker on Meades Ranch in Kansas as 39° 13' 26.71218" N, 98° 32' 31.74604" W. Using NAD 27, every other point in North America was measured from this one point.

Each datum has a corresponding spatial reference identifier or SRID. The census Shapefile we used was built with the North American Datum of 1983, or NAD 83, an update to NAD 27. A query of SQL Server's sys.spatial_reference_systems table reveals that the corresponding SRID for NAD 83 is 4269.

Incidentally, most GPS devices use the World Geodetic System of 1984 (WGS 84), which corresponds with SQL Server's default SRID of 4326. NAD 83 and WGS 84 are essentially interchangeable for all but the most accurate applications. Given a set of coordinates, the location measured with NAD 83 will be at most, about one meter away from the location measured with WGS 84. That is, the two systems differ by about one meter at most.

Spatial data types

Spatial data can be broken down into three essential data types. First, a point consists of a simple X and Y coordinate. It has no length or area. A linestring is simply two or more points in sequence, and the shortest possible line from each point to the next, as shown in the following diagrams. It has length, but no area. There are two special cases. A simple linestring is one that doesn't cross itself. A ring is a linestring whose first point is the same as its last.

Spatial data types

In its most basic form, a polygon is a simple ring. It has length (or rather perimeter), as well as area. As shown in the second diagram, the line string forming the perimeter of the polygon must be simple; it cannot cross over itself to form a bow tie. A polygon may have inner negative areas defined with inner rings. The linestrings forming these rings may touch, but they can never cross each other or the outside ring. This can best be explained with the following diagrams:

Spatial data types
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.98.148