I have database and in it I have class hotel with gps coordinates. I want to get closest places to coordinates which I choose.
I think It should look like this (I found
I post here my solution which I am using for now. But I choose GwynnBliedd answer because he solves my problem in question.
I added DbGeography type to my class and I am using it instead of saving latitude and longitude in database.
locationField = DbGeography.FromText(String.Format("POINT({0} {1})", orig.gps.lat.ToString().Replace(",", "."), orig.gps.lng.ToString().Replace(",", ".")));
Then it's very easy to use linq:
var coord = DbGeography.FromText(String.Format("POINT({0} {1})", latitude.ToString().Replace(",", "."), longitude.ToString().Replace(",", ".")));
var nearest = (from h in db.hotels
where h.location != null
orderby h.location.Distance(coord)
select h).Take(limit);
return nearest;
For now this is working solution and it's good. For sometime I would be using this but as few users said here I'll maybe try UDF with implementing Haversine formula (like in this answer).
You can use the object initializer instead of parameterized constructor:
var nearest = (from h in db.hotels
let geo = new GeoCoordinate{ Latitude = h.gps.lat, Longitude = h.gps.lng}
orderby geo.GetDistanceTo(coord)
select h).Take(10);
But you will likely have problems caused by the GetDistanceTo method, could you provide the implementation of that method?
I have had a reasonable about of success using this implementation of the Haversine Distance formula
var startPoint = new { Latitude = 1.123, Longitude = 12.3 };
var closest = entities.Something.OrderBy(x => 12742 * SqlFunctions.Asin(SqlFunctions.SquareRoot(SqlFunctions.Sin(((SqlFunctions.Pi() / 180) * (x.Latitude - startPoint.Latitude)) / 2) * SqlFunctions.Sin(((SqlFunctions.Pi() / 180) * (x.Latitude - startPoint.Latitude)) / 2) +
SqlFunctions.Cos((SqlFunctions.Pi() / 180) * startPoint.Latitude) * SqlFunctions.Cos((SqlFunctions.Pi() / 180) * (x.Latitude)) *
SqlFunctions.Sin(((SqlFunctions.Pi() / 180) * (x.Longitude - startPoint.Longitude)) / 2) * SqlFunctions.Sin(((SqlFunctions.Pi() / 180) * (x.Longitude - startPoint.Longitude)) / 2)))).Take(5);