【问题标题】:Query nearby locations in table in ASP.NET Core 2 and Entity Framework Core 2在 ASP.NET Core 2 和 Entity Framework Core 2 中查询表中的附近位置
【发布时间】:2018-08-14 18:29:30
【问题描述】:

我正在尝试进行查询,以便在我的 SQL 数据库中找到给定经度和纬度点(比如说 50 英里)内的所有位置。

我填充了一些帖子,在帖子表中,我有两列在创建帖子时存储经度和纬度。以下是表格的外观:

我浏览了许多有关如何尝试实现此功能的示例,但似乎它们根本不起作用。我通过研究得知 ASP.NET Core 不支持DbGeography,其他文章只是过时了。

找到了这个article,但它使用了DbGeography,所以这不起作用。

在 GitHub 上找到了这个:here 我只是不知道这是否可行。

仅供参考,这是我的 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);
    }       
}

有人对如何实现这样的查询有任何见解吗?

【问题讨论】:

标签: c# asp.net entity-framework geocoding asp.net-core-2.0


【解决方案1】:

如果您从数据库中提取适合您所需距离圆圈周围正方形的数据,然后在客户端微调到圆圈中的帖子怎么样?

鉴于您的初始数据

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;

然后你可以在数据库中查询广场内的那些帖子,把它们带到客户那里,只保留圈子里的那些

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。

【讨论】:

  • 让我去试试@NetMage
  • 我在我的查询中实现了它,并用不同的位置点和英里半径对其进行了测试,效果很好。我现在必须从前端的搜索字符串中传递经度和纬度,并使其动态化,这应该很容易。谢谢@NetMage。
【解决方案2】:

他们在 Entity Framework Core 2.2 版中引入了空间数据支持。

你可以看看这个StackOverflow answer

【讨论】:

    猜你喜欢
    • 2020-11-25
    • 2018-09-03
    • 2017-12-22
    • 1970-01-01
    • 2018-07-31
    • 1970-01-01
    • 2018-09-28
    • 2018-11-05
    • 2022-01-25
    相关资源
    最近更新 更多