Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spatial type Entity Framework Core SQL Server

I need to work with georaphic distances.

I got

public class Clinic
{
    ...
    public double Latitude
    public double Longitud
    ...
}

This clinics are on a SQL Server DB. I need to return them ordered by distance to a certain point. For what I read, Entity Framework Core has no support for DbGeography or something of that sort as to represent the SQL Server type:

geography

I added to the database a column with the calculated geography point of each clinic

UPDATE Clinics SET Geo = geography::Point(Clinics.Latitude, Clinics.Longitud,4326)

OK, know i need to return them ordered. SQL supports this by querying

DECLARE @p geography;
SET @p = geography::Point(41,2,4326);
SELECT * FROM Clinics c ORDER BY @p.STDistance(c.Geo);

and Entity Framework Core supports querying with a raw SQL.

context.Clinics.FromSql("..query..")

Thing is, as the documentation of the FromSql says, if the data you are returning doesn't exactly match the model it crashes. As in C# I cant have a DbGeography that represents Geo I can't figure out how to resolve this.

EDIT 1:

Got it to partially work with the following:

string rawSQL = @"
        DECLARE @p geography;
        SET @p = geography::Point(41,2,4326);
        SELECT c.Id, c.Name, c.Price, c.Quote, c.QuoteAuthor, c.QuoteSource, c.Description, c.Image, c.Latitude, c.Longitude, c.Category, c.CenterDistance, c.NumReviews, c.Stars
        FROM Clinics c
        ORDER BY @p.STDistance(c.Geo); ";
query = query.FromSql(rawSQL);

So now I get all the attributes of Clinics and it works! Thing is, clinics has a related class Amenities

public class Clinic
{
    ...
    public double Latitude
    public double Longitud
    public Amenity amenity
    ...
}

So when I run a query I need to include the amenities by linq

query = query.Include(c => c.ClinicAmenities).ThenInclude(ca => ca.Amenity);

Dies because Orderby from the raw sql comes before the include I believe

like image 914
Guido Dizioli Avatar asked May 19 '17 13:05

Guido Dizioli


People also ask

What is spatial data types in SQL?

SQL Server supports two spatial data types: the geometry data type and the geography data type. The geometry type represents data in a Euclidean (flat) coordinate system. The geography type represents data in a round-earth coordinate system.

What is Entity Framework core SQL Server?

Entity Framework Core is a modern object-database mapper for . NET. It supports LINQ queries, change tracking, updates, and schema migrations. EF Core works with many databases, including SQL Database (on-premises and Azure), SQLite, MySQL, PostgreSQL, and Azure Cosmos DB.

What is NetTopologySuite?

NetTopologySuite (NTS) is a spatial library for . NET. EF Core enables mapping to spatial data types in the database by using NTS types in your model.

What is difference between geography and geometry in SQL Server?

The connecting edge between two vertices in a geometry type is a straight line. However, the connecting edge between two vertices in a geography type is a short great elliptic arc between the two vertices.


1 Answers

You didn't specify what error you get.

It seems to me you get error "The Include operation is not supported when calling a stored procedure."

What you could do is execute two queries.

Something like this

dbContext.Amenities.Load();

string rawSQL = @"
          DECLARE @p geography;
          SET @p = geography::Point(41,2,4326);
          SELECT c.Id, c.Name, c.Price, c.Quote, c.QuoteAuthor
          FROM Clinics c
          ORDER BY @p.STDistance(c.Geo)";

// EF will automatically wire up the references between entities 
// that have been queried for
var clinicsWithAmenities = dbContext.Clinics.FromSql(rawSQL).ToList();
like image 190
Zeljko Vujaklija Avatar answered Sep 28 '22 08:09

Zeljko Vujaklija