惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
Recent Announcements
Recent Announcements
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The GitHub Blog
The GitHub Blog
MyScale Blog
MyScale Blog
爱范儿
爱范儿
GbyAI
GbyAI
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
美团技术团队
Y
Y Combinator Blog
博客园 - 叶小钗
Apple Machine Learning Research
Apple Machine Learning Research
Martin Fowler
Martin Fowler
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
罗磊的独立博客
M
MIT News - Artificial intelligence
博客园 - Franky
V
Visual Studio Blog
I
InfoQ
V
V2EX
Hugging Face - Blog
Hugging Face - Blog
腾讯CDC
博客园 - 司徒正美
L
LangChain Blog

博客园 - 饭

This MySqlConnection is already in use. See https://fl.vu/mysql-conn-reuse WinForm使用Python.Net调用Yolov8将图像显示在pictureBox控件上. EPPlus操作透视表过滤数据 JS/html5 文字转语音 关于IIS部署.NET7的记录 nginx伪静态过滤静态文件 阿里云Nginx伪静态 记录一些壁纸/图片网站 js四舍五入. javascript四舍五入 真正四舍五入 不是四舍六入五成双 比较两个相同类型的实例是否相同, 支持忽略指定字段. 正padding负margin实现多列等高布局(转) 在iframe内页触发顶层页面body的blur事件 bootstrap 模态窗口 多重/多个弹窗滚动条补丁 2019年6月车型数据Access数据库+缩略图 更新于2019年6月5日. sql server 2012 分页/dapper/C#拼sql/免储存过程/简易 正则: 匹配除了某些单词之外的其他单词 按顺序动态加载js, 可控版本, 有回调 asp.net mvc json数据缓存 知识点关键词(记录一下) TimeSpan格式化字符串格式(摘)
entity framework 实现按照距离排序[转]
· 2019-12-28 · via 博客园 - 饭

原文地址: https://www.cnblogs.com/hucheng/p/9885573.html

sql实现方式

SELECT
    es_name,
    es_lon,
    es_lat,
    ROUND(
        6378.138 * 2 * ASIN(
            SQRT(
                POW(
                    SIN(
                        (
                            30.611842 * PI() / 180 - es_lat * PI() / 180
                        ) / 2
                    ),
                ) + COS(30.611842 * PI() / 180) * COS(es_lat * PI() / 180) * POW(
                    SIN(
                        (
                            104.074666 * PI() / 180 - es_lon * PI() / 180
                        ) / 2
                    ),
                )
            )
        ) * 1000
    ) AS distance_um
FROM
    c_ershuai
ORDER BY
    distance_um ASC

以下是我采用的方案

首先定义一个接口,用来表示具有经纬度信息的实体。

/// <summary>
/// 具有经纬度
/// </summary>
public interface IHasLngAndLat
{
    /// <summary>
    /// 经度
    /// </summary>
    double Lng { get; set; }
    /// <summary>
    /// 纬度
    /// </summary>
    double Lat { get; set; }
}

然后创建泛型类,用来包装计算的距离。

/// <summary>
/// 带距离的数据
/// </summary>
/// <typeparam name="TEntity"></typeparam>
public class DataWithDistance<TEntity>
{
    /// <summary>
    /// 距离(km)
    /// </summary>
    public double Distance { get; set; }
    /// <summary>
    /// 实体数据
    /// </summary>
    public TEntity Entity { get; set; }
}

最后编写根据距离排序的扩展方法

注意:这个方法是采用的  SqlFunctions 类,所以仅支持  SqlServer  数据库,如果是其它数据库,需要将  SqlFunctions   更换成对应的类

/// <summary>
/// IQueryable扩展类
/// </summary>
public static class QueryableExtension
{
    /// <summary>
    /// 根据距离排序
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    /// <param name="queryable"></param>
    /// <param name="lng">经度</param>
    /// <param name="lat">纬度</param>
    /// <returns></returns>
    public static IQueryable<DataWithDistance<TEntity>> OrderByDistance<TEntity>(this IQueryable<TEntity> queryable, double lng, double lat) where TEntity : class, IHasLngAndLat
    {
        var rtn = from q in queryable
                  let radLat1 = lat * Math.PI / 180.0
                  let radLat2 = q.Lat * Math.PI / 180.0
                  let a = radLat1 - radLat2
                  let b = lng * Math.PI / 180.0 - q.Lng * Math.PI / 180.0
                  let s = 2 * SqlFunctions.Asin(SqlFunctions.SquareRoot(Math.Pow((double)SqlFunctions.Sin(a / 2), 2) +
           SqlFunctions.Cos(radLat1) * SqlFunctions.Cos(radLat2) * Math.Pow((double)SqlFunctions.Sin(b / 2), 2))) * 6378.137
                  let d = Math.Round((double)s * 10000) / 10000
                  orderby d
                  select new DataWithDistance<TEntity> { Entity = q, Distance = d };

        return rtn;
    }
}

以上就完成了 entity framework 按照距离排序的功能。

接下来我们用它来写一个小小的demo

首先创建一个商店实体类,具有经纬度字段,实现了 IHasLngAndLat  接口

/// <summary>
/// 商店实体
/// </summary>
public class Shop : IHasLngAndLat
{
    /// <summary>
    /// 主键
    /// </summary>
    public int Id { get; set; }
    /// <summary>
    /// 商店名称
    /// </summary>
    [Required]
    [StringLength(64)]
    public string ShopName { get; set; }
    /// <summary>
    /// 经度
    /// </summary>
    public double Lng { get; set; }
    /// <summary>
    /// 纬度
    /// </summary>
    public double Lat { get; set; }
}

然后创建EF上下文类

/// <summary>
/// EF上下文
/// </summary>
public class DemoDbContext : DbContext
{
    public DemoDbContext()
        : base("name=DemoDbContext")
    {
    }
    public virtual DbSet<Shop> Shop { get; set; }
}

最后我们分页查询商店,并按照距离由近到远排序

double user_lng = 113.46, user_lat = 22.27;  //用户经纬度
int pageIndex = 3; //当前页码
int pageSize = 10; //每页条数


using (DemoDbContext context = new DemoDbContext())
{
    var queryable = context.Shop.AsNoTracking().AsQueryable();
    IQueryable<DataWithDistance<Shop>> sort_queryable = queryable.OrderByDistance(user_lng, user_lat);  //按照用户的距离从近到远排序
    List<DataWithDistance<Shop>> data = sort_queryable.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();   //分页并执行sql查询获取数据

    //TODO:将查到的数据映射成DTO对象,并返回给客户端
}

好了,entity framework 实现按照距离排序 也就全部完成了。