You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于经纬度距离计算方法对BO_MAGASIN列表进行排序

实现方案

你可以根据你的数据量选择以下两种方案:

方案1:内存中排序(适合小数据量场景)

基于你现有的距离计算方法,直接配合LINQ实现排序,步骤如下:

  1. 首先优化你现有的CalculateDistance方法(原方法每次调用都创建数据库连接、拼接SQL存在注入风险、还有冗余查询,性能极低,建议替换为C#本地实现的Haversine公式计算经纬度距离):
// 优化后的本地距离计算方法,单位:公里
public double CalculateDistance(double baseLat, double baseLng, double targetLat, double targetLng)
{
    const double EarthRadius = 6371; // 地球半径,单位公里
    var latDiff = ToRadians(targetLat - baseLat);
    var lngDiff = ToRadians(targetLng - baseLng);
    var a = Math.Sin(latDiff / 2) * Math.Sin(latDiff / 2) +
            Math.Cos(ToRadians(baseLat)) * Math.Cos(ToRadians(targetLat)) *
            Math.Sin(lngDiff / 2) * Math.Sin(lngDiff / 2);
    var c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
    return EarthRadius * c;
}

// 角度转弧度辅助方法
private double ToRadians(double angle)
{
    return angle * Math.PI / 180;
}

// 适配你原有入参的重载方法
public double CalculateDistance(string baseStoreId, BO_MAGASIN targetMag)
{
    // 只查询一次基准点坐标,不要每次调用都查库
    var baseMag = _context.Magasin.FirstOrDefault(x => x.storelocator_id.Equals(baseStoreId));
    if (baseMag == null || targetMag == null) return double.MaxValue;
    // 注意把你存的字符串类型经纬度转成double
    if (!double.TryParse(baseMag.latitude, out var baseLat) 
        || !double.TryParse(baseMag.longitude, out var baseLng)
        || !double.TryParse(targetMag.latitude, out var targetLat)
        || !double.TryParse(targetMag.longitude, out var targetLng))
    {
        return double.MaxValue;
    }
    return CalculateDistance(baseLat, baseLng, targetLat, targetLng);
}
  1. 拿到BO_MAGASIN列表后直接排序:
// 你的BO_MAGASIN列表
List<BO_MAGASIN> magasinList = GetYourMagasinList();
// 以storelocator_id为1的点为基准,按距离从近到远排序
var sortedList = magasinList.OrderBy(m => CalculateDistance("1", m)).ToList();
// 如果要从远到近就用OrderByDescending

方案2:数据库层面排序(适合大数据量场景,性能最优)

直接在查询列表的时候用MySQL自带的空间函数计算距离并排序,不需要把全量数据拉到内存处理:

public List<BO_MAGASIN> GetSortedMagasinList(string baseStoreId)
{
    var baseMag = _context.Magasin.FirstOrDefault(x => x.storelocator_id.Equals(baseStoreId));
    if (baseMag == null) return new List<BO_MAGASIN>();
    string sql = @"SELECT * FROM magasin 
                    ORDER BY ST_Distance_Sphere(point(@baseLng, @baseLat), point(longitude, latitude))/1000 ASC";
    string dbConn = configuration.GetSection("ConnectionStrings").GetSection("Default").Value;
    using var conn = new MySqlConnection(dbConn);
    conn.Open();
    // 参数化查询避免SQL注入
    var command = new MySqlCommand(sql, conn);
    command.Parameters.AddWithValue("@baseLat", double.Parse(baseMag.latitude));
    command.Parameters.AddWithValue("@baseLng", double.Parse(baseMag.longitude));
    using var reader = command.ExecuteReader();
    var result = new List<BO_MAGASIN>();
    while (reader.Read())
    {
        // 填充BO_MAGASIN对象逻辑,和你原来获取列表的逻辑保持一致即可
        result.Add(new BO_MAGASIN
        {
            storelocator_id = reader["storelocator_id"].ToString(),
            latitude = reader["latitude"].ToString(),
            longitude = reader["longitude"].ToString(),
            // 其他字段赋值
        });
    }
    return result;
}

注意事项

  • 原有的CalculateDistance方法存在SQL注入风险、冗余查询、吞异常等问题,建议优先优化
  • 如果你的经纬度字段存储类型是字符串,转换double的时候要做好异常处理,避免格式错误导致程序崩溃

内容的提问来源于stack exchange,提问作者user8065759

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.14 00:48:01