We use ASP.NET Core 5 backend with SQL Server v15 and Entity framework V5, and there's something intriguing that I was struggling with, consider this:
You have a table as below:
CREATE TABLE [dbo].[ContactDetails](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](128) NOT NULL,
...
[Geolocation] [geography] NULL
)
That table is used by other tables, eg. Stores., to store contact details.
Table ContactDetails is then automatically scaffolded as below:
public partial class ContactDetail
{
public ContactDetail()
{
Stores = new HashSet<Store>();
}
public int Id { get; set; }
public string Name { get; set; }
public Geometry Geolocation { get; set; }
}
Then you store Stores' longitude and latitude (double) from input let's say as:
Geometry Store.ContactDetails.Geolocation = new NetTopologySuite.Geometries.Point(store.longitude, store.latitude) { SRID = 4326 };
Now given a location from a user, which was created the same way
Geometry userLocation = new NetTopologySuite.Geometries.Point(user.longitude, user.latitude) { SRID = 4326 };
You want to know how far is each Store from the user. How would you do that?
I did this:
DbContext dbContext; //...somehow constructed
var dbSet = dbContext.Set<Store>();
var distances = dbSet.Where(...).Select(store => store.ContactDetails.Geolocation.Distance(userLocation));
But to my surprise the distances are completely off! I expected that the distances are returned in degrees and I'll will have to convert that to Kms. But these numbers are completely off (like 83130).
So I tried this:
var anotherDistances = dbSet.Where(...).AsEnumerable().Select(store => store.ContactDetails.Geolocation.Distance(userLocation));
And this time the distances are as expected (eg. 1.245 degrees).
What happened there?
I need to keep the results as IQueryable
so I can do efficiently further filtering and transformations. How can I get correct distances without having to convert IQueryable
to IEnumerable
?
I could not find the answer from other questions, I suspect that Linq could not translate the query into SQL correctly and that querying after AsEnumerable()
was able to use the correct type inferring and use spatial correct methods when it loaded objects in memory. But this is just some hazy understanding. I'd really appreciate if you could help me understand this.