查询表附近的位置在ASP.NET的Core 2和Entity Framework的Core 2

问题描述 投票:0回答:3

我试图做一个查询在哪里可以找到在我内的SQL数据库的所有位置(可以说50英里)给定的经度和纬度点。

我居住的一些帖子,并在帖子表我有,我在创建后,当存储经度和纬度两列。下面是表的外观:

My SQL Server 2012 Post Table

我浏览过的如何尝试实施许多这样的例子,但似乎他们只是不工作。我从研究的是ASP.NET核心不支持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...
}

这是我做我的查询截至目前在我的谷歌地图在前台显示点:

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
3个回答
3
投票

怎么样,如果你解压缩在客户端从适合摆放在你的所需距离的圆方数据库中的数据,然后微调,只是在中圈的职位?

鉴于你的初始数据

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;
}

我使用余弦的球形法计算的距离,我以为就足够了这个问题。如果您需要更准确,你可以升级配方更复杂的东西像半正矢或Vincenty。


1
投票

他们推出与实体框架核心的2.2版本的空间数据支持。

你可以看看这个StackOverflow answer


0
投票

没有与NetMage's答案的一个缺陷。

对于负经度/纬度,maxLat / maxLon会比你minLat / minLon较低,您的查询将寻找边界框之外。

下面是基于他的回答计算边框正确的方式之一(这种方式,可以确保最低总是低于最大值)

var minMilePerLat = 68.703;
var milePerLon = Math.Cos(myLat) * 69.172;
var minLat = Math.min(myLat - radiusInMile / minMilePerLat, myLat + radiusInMile / minMilePerLat);
var maxLat = Math.max(myLat - radiusInMile / minMilePerLat, myLat + radiusInMile / minMilePerLat);
var minLon = Math.min(myLon - radiusInMile / milePerLon, myLon + radiusInMile / milePerLon);
var maxLon = Math.max(myLon - radiusInMile / milePerLon, myLon + radiusInMile / milePerLon);

您还可以更改,当你基于最小和最大查询的东西,但我想这是更简单。

© www.soinside.com 2019 - 2024. All rights reserved.