is there something like dbgeometry makevalid in .net 4.5
Asked Answered
S

4

4

I'm trying to calculate area of polyline like that

    string poly = "POLYGON ((637604.918432772 2230520.64934531,
637622.257266129 2230419.44632915, 637279.107128549 2230192.04910755, 636765.470527745 2230179.6468564, 636778.005055813 2229861.77192838, 636529.81646905 2229464.29327025, 635813.486592791 2229523.30345774, 636017.385069448 2229974.32341381, 636267.323659164 2230070.32127916, 637035.026966561 2230404.70764784, 637275.265066307 2230401.13408429, 637604.918432772 2230520.64934531, 637604.918432772 2230520.64934531))";
     DbGeometry gm = DbGeometry.FromText(poly, 32637);
double area= gm.Area.Value; // here I got the error Exception has been thrown by the target of an invocation.

I noticed later that the reson of error that the dbgeometry is invalid I try the code in ms sql 2012 also give me the error but when I tried like that

SELECT @gm.MakeValid().STArea()

thats worked in sql my question is there is away to make the geometry valid in .net thank you

Shoffner answered 19/5, 2013 at 23:28 Comment(0)
O
6

I'd agree with Bojan, unless you are using the Entity Framework?

The SqlGeometry object has a MakeValid() function, so using your example, allowing for a convert between DbGeography and SqlGeography:

DbGeography geog;
SqlGeometry geom = SqlGeometry.STGeomFromWKB(new SqlBytes(geog.AsBinary()), 32637);

However, unless you are using EF, I'd recommend simply using SqlGeometry as

  1. There is no cast / conversion
  2. SqlGeometry has far more functions available than DbGeometry.

Hope that helps.

Occupier answered 29/5, 2013 at 10:53 Comment(2)
I'm using entity framework 5 can i use sqlgeometry then assign it to dbgeometryShoffner
@Khalid, ultimately, yes, you're restricted to DBGeometry within EF5 but you can read it from the DB, convert it to SQLGeometry, perform whatever you need to, convert it back to DBGeometry and update the DB (if needed). However, whilst a single conversion is a negligible overhead, this can quickly become significant when doing with large quantities of objects. My question to you is therefore, why exactly do you HAVE to convert it, there are valid reasons, but I'm trying to make sure I best advise.Occupier
B
9

You definitely should not go to the DB to get what you want. A simple and fast method is to extend DbGeography by adding the following code to your project:

using System.Data.SqlTypes;
using Microsoft.SqlServer.Types;

namespace System.Data.Spatial
{
    public static class DbGeometryExtension
    {
        public static DbGeometry MakeValid(this DbGeometry geom)
        {
            if (geom.IsValid)
                return geom;

            return DbGeometry.FromText(SqlGeometry.STGeomFromText(new SqlChars(geom.AsText()), 4326).MakeValid().STAsText().ToSqlString().ToString(), 4326);

        }
    }
}

There are a few assumptions made when creating this code so don't use it "as is".

Ballinger answered 6/10, 2013 at 21:34 Comment(2)
Actually we dolike thisShoffner
Note that the projection above is 32637 and not 4326Arrange
O
6

I'd agree with Bojan, unless you are using the Entity Framework?

The SqlGeometry object has a MakeValid() function, so using your example, allowing for a convert between DbGeography and SqlGeography:

DbGeography geog;
SqlGeometry geom = SqlGeometry.STGeomFromWKB(new SqlBytes(geog.AsBinary()), 32637);

However, unless you are using EF, I'd recommend simply using SqlGeometry as

  1. There is no cast / conversion
  2. SqlGeometry has far more functions available than DbGeometry.

Hope that helps.

Occupier answered 29/5, 2013 at 10:53 Comment(2)
I'm using entity framework 5 can i use sqlgeometry then assign it to dbgeometryShoffner
@Khalid, ultimately, yes, you're restricted to DBGeometry within EF5 but you can read it from the DB, convert it to SQLGeometry, perform whatever you need to, convert it back to DBGeometry and update the DB (if needed). However, whilst a single conversion is a negligible overhead, this can quickly become significant when doing with large quantities of objects. My question to you is therefore, why exactly do you HAVE to convert it, there are valid reasons, but I'm trying to make sure I best advise.Occupier
A
4

SqlSpatialFunctions.MakeValid is a SQL Server-specific method to do that.

If you are interested why your geometry is invalid, you can ask SQL Server:

SELECT @gm.IsValidDetailed()

Also, you might want to consider using SQL Server geometry type directly: SqlGeometry.MakeValid.

Affricate answered 20/5, 2013 at 0:24 Comment(3)
how can I use SqlSpatialFunctions with in c# to dbgeometry validShoffner
gm = SqlSpatialFunctions.MakeValid(gm); give me This function can only be invoked from LINQ to Entities.Shoffner
Ah, sorry, my bad - that seems to be just a way to get LINQ to invoke SQL's MakeValid on database objects. I've updated my answer.Affricate
S
0

here a medium solve to that problem that i make scallar function like that

CREATE FUNCTION [dbo].[GeomMakeValid](@geom as geometry)
RETURNS geometry
AS
BEGIN

DECLARE @gm as geometry;
set @gm = @geom.MakeValid();

return (@gm);
END

GO

then i call it from model like that

public static DbGeometry geoMakeValid(DbGeometry geom)
      {

          EntityConnection Connec = getConnection();

          DbCommand com = Connec.StoreConnection.CreateCommand();
          com.CommandText = "select dbo.GeomMakeValid(@geom)";
          com.CommandType = System.Data.CommandType.Text;
          com.Parameters.Add(new SqlParameter("@geom", geom.AsText()));
          if (com.Connection.State == ConnectionState.Closed) com.Connection.Open();
          try
          {
              var result = com.ExecuteScalar(); // should properly get your value
              Connec.Close();
              return DbGeometry.FromText( result.ToString(),geom.CoordinateSystemId);

          }
          catch (System.Exception e)
          {

          }
          Connec.Close();
          return geom;
      }

any any part of code i can call this function to make geometry valid

Shoffner answered 26/5, 2013 at 9:25 Comment(1)
Since your code is already SQL Server specific, then it would be much cleaner and faster to use SqlGeometry objects in your code instead of DbGeometry, rather than doing the entire roundtrip to the database.Affricate

© 2022 - 2024 — McMap. All rights reserved.