查询ASP.NET Core 2和Entity Framework Core 2中表中的附近位置
我正在尝试查询我可以在我的SQL数据库中查找给定经度和纬度点内的所有位置(比如50英里)。
我填充了一些post,在Post表中我有两列,我在创建post时存储经度和纬度。 以下是该表的外观:
我已经浏览了许多如何尝试实现这一点的例子,但似乎它们只是不起作用。 我知道从研究ASP.NET Core不支持DbGeography
,其他文章刚刚过时。
发现这篇文章 ,但它使用DbGeography
,因此不起作用。
在GitHub上找到了这个: 在这里我只是不知道这是否会起作用。
仅供参考,这是我的Post模型的外观:
public class Post { public int Id { get; set; } public string Title { get; set; } public double Lat { get; set; } public double Lng { get; set; } public DateTime Created { get; set; } public Category Category { get; set; } public int CategoryId { get; set; } // Other navigation properties... }
这就是我现在的查询方式,即在前端的Google地图上显示点:
public class HomeController : Controller { private readonly ApplicationDbContext _context; public HomeController(ApplicationDbContext context) { _context = context; } [HttpGet] public JsonResult GetGalleryLocations() { var data = _context.Posts .Include(c => c.Category) .ToList(); return Json(data); } }
有没有人对如何实现这样的查询有任何见解?
如果你从数据库中提取适合你所需距离的广场周围的数据,然后在客户端微调到圆圈中的post怎么样?
鉴于您的初始数据
var myLat = 25.05; var myLon = -80.3; var radiusInMile = 50;
您可以计算包含该圆的正方形的边界
var minMilePerLat = 68.703; var milePerLon = Math.Cos(myLat) * 69.172; var minLat = myLat - radiusInMile / minMilePerLat; var maxLat = myLat + radiusInMile / minMilePerLat; var minLon = myLon - radiusInMile / milePerLon; var maxLon = myLon + radiusInMile / milePerLon;
然后,您可以在数据库中查询广场内的那些post,将它们带到客户端并保留在圈子中的那些post
var data = _context.Posts .Where(p => (minLat <= p.Lat && p.Lat <= maxLat) && (minLon <= p.Lng && p.Lng <= maxLon)) .AsEnumerable() .Select(p => new { p, Dist = distanceInMiles(myLon, myLat, p.Lng, p.Lat) }) .Where(p => p.Dist <= radiusInMile);
distanceInMiles
函数定义为
public double ToRadians(double degrees) => degrees * Math.PI / 180.0; public double distanceInMiles(double lon1d, double lat1d, double lon2d, double lat2d) { var lon1 = ToRadians(lon1d); var lat1 = ToRadians(lat1d); var lon2 = ToRadians(lon2d); var lat2 = ToRadians(lat2d); var deltaLon = lon2 - lon1; var c = Math.Acos(Math.Sin(lat1) * Math.Sin(lat2) + Math.Cos(lat1) * Math.Cos(lat2) * Math.Cos(deltaLon)); var earthRadius = 3958.76; var distInMiles = earthRadius * c; return distInMiles; }
我使用余弦的球面定律来计算距离,我认为这足以解决这个问题。 如果您需要更高的准确度,可以将公式升级为更复杂的东西,如hasrsine或Vincenty。