locked
Constructing DbGeography RRS feed

  • Question

  • Hello,

    Is there any other way of building DbGeography besides from WKT, WKB and GML. May be something implementing IGeographySink? If not now, do you plan to put something in the final release?

    Thanks

    Val


    Thanks
    • Edited by Valo Wednesday, October 12, 2011 4:56 AM
    Wednesday, October 12, 2011 4:55 AM

Answers

  • Unfortunately the only ways to construct DbGeometry and DbGeography values are from WKT, WKB and GML.   We looked at implementing IGeographySink, but that would have required us to take a static dependency on the Microsoft.SqlServer.Types.dll, which we simply couldn't do.   So for the upcoming version of EF this is all that we will provide.

    DbGeometry and DbGeography are implemented as thin wrappers over some underlying implementation of spatial functionality.    If you are talking to Sql Server, you have to have Microsoft.SqlServer.Types.dll installled.   In this case, the DbGeography value contains a SqlGeography value and a reference to a DbSpatialServices object that bridges between the sql server type and Dbgeography.   If you are using a different store, it may encapsulate different values.

    There is a notion of the default spatial service (System.Spatial.DbSpatialServices.Default).   In the simplest case it provides a backing implementation that is just storage for SRIDs, WKT values, WKB values and Gml values.   It isn't able to do *anything* else.   For example, it can't even tell you the Longitude of a geographic point.    This is adequate for some scenarios, but fails in others.   As a result, we make an effort to provide more functionality if we can.    If Microsoft.SqlServer.Types.dll is installed, System.Spatial.DbSpatialServices.Default is a provider that uses the SqlServer types.   In practice, if you want to communicate spatial types to Sql Server, having this assembly installed is a requirement.

    This suggests the following workaround.  

    Construct an object g of type SqlGeography using IGeographySink, and then call System.Spatial.DbSpatialServices.Default.Geography.GeographyFromProviderValue(g) to get a DbGeography.   As long as the default spatial service is the SqlSpatialServices implementation, this will do the expected thing.   If it isn't, it will throw an error.

    Hope this helps

    Will.

    • Marked as answer by Valo Thursday, October 13, 2011 2:03 AM
    Wednesday, October 12, 2011 6:08 PM

All replies

  • Unfortunately the only ways to construct DbGeometry and DbGeography values are from WKT, WKB and GML.   We looked at implementing IGeographySink, but that would have required us to take a static dependency on the Microsoft.SqlServer.Types.dll, which we simply couldn't do.   So for the upcoming version of EF this is all that we will provide.

    DbGeometry and DbGeography are implemented as thin wrappers over some underlying implementation of spatial functionality.    If you are talking to Sql Server, you have to have Microsoft.SqlServer.Types.dll installled.   In this case, the DbGeography value contains a SqlGeography value and a reference to a DbSpatialServices object that bridges between the sql server type and Dbgeography.   If you are using a different store, it may encapsulate different values.

    There is a notion of the default spatial service (System.Spatial.DbSpatialServices.Default).   In the simplest case it provides a backing implementation that is just storage for SRIDs, WKT values, WKB values and Gml values.   It isn't able to do *anything* else.   For example, it can't even tell you the Longitude of a geographic point.    This is adequate for some scenarios, but fails in others.   As a result, we make an effort to provide more functionality if we can.    If Microsoft.SqlServer.Types.dll is installed, System.Spatial.DbSpatialServices.Default is a provider that uses the SqlServer types.   In practice, if you want to communicate spatial types to Sql Server, having this assembly installed is a requirement.

    This suggests the following workaround.  

    Construct an object g of type SqlGeography using IGeographySink, and then call System.Spatial.DbSpatialServices.Default.Geography.GeographyFromProviderValue(g) to get a DbGeography.   As long as the default spatial service is the SqlSpatialServices implementation, this will do the expected thing.   If it isn't, it will throw an error.

    Hope this helps

    Will.

    • Marked as answer by Valo Thursday, October 13, 2011 2:03 AM
    Wednesday, October 12, 2011 6:08 PM
  • Thanks, Will.

    This not only helps but works well (I cannot believe I didn't even considered the method GeographyFromProviderValue...) Here is my working test just in case someone would like to use your advice:

    using System;
    using System.Data.Spatial;
    using Microsoft.SqlServer.Types;
    using System.IO;
     
    namespace GeographyCtor
    {
        class Program
        {
            static void Main(string[] args)
            {
                var builder = new SqlGeographyBuilder();
     
                builder.SetSrid(4326);            
                builder.BeginGeography(OpenGisGeographyType.Point);
                builder.BeginFigure(47.65100, -122.34900, 300, 34.5);
                builder.EndFigure();
                builder.EndGeography();
     
                var geo = DbSpatialServices.Default.GeographyFromProviderValue(builder.ConstructedGeography);
     
                Console.WriteLine("Geo({0}, {1}, {2}, {3})\n", geo.Latitude, geo.Longitude, geo.Z, geo.M);
            }
        }
    }
    

    Of course now the static dependency on Microsoft.SqlServer.Types is in my code but I'll think of way around it.

    Thanks.


    Thanks
    Thursday, October 13, 2011 2:17 AM
  • After working a few days with the EF spatial types in the preview I have mixed feelings about them.

    I am not sure if I am right about it but it seems to me that having the two base classes DbGeography and DbGeometry is a little artificial. Just because they describe geometric objects in different types of planes and coordinates it is still not good enough reason to have two different base types. After all one still cannot mix and match objects in the flat plane with different SRID-s or geo objects with spherical coordinates with different SRID-s and that does't mean that we need thousands of basic types.

    It seems to me that a better taxonomy would be based on the shape of the described objects (points, polygons, multi-line strings, etc.) I think that there is actually open source set of interfaces out there that adhere to that view (GeoAPI and NetTopologySuite). From OOP textbook cases point of view these feel much more natural. Why do I need to build a super-set of functionality which takes into account the actual shape of the geometry? (In a somewhat related point, isn't it time that you guys open EF for extensions: user types, linq extensions, db/code name conventions, etc.)

    I (and probably others) would love to hear your thoughts and future plans for support of spatial types.

    Val


    Thanks
    Wednesday, October 19, 2011 6:49 PM