entity framework 实现按照距离排序
在做项目时,经常会遇到“离我最近”这种需求。顾名思义,它需要根据用户的经纬度和事物的经纬度计算距离,然后进行排序,最后分页(当然这些操作要在数据库中进行,否则就变成假分页了)。
我们通常可以用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
),
2
) + COS(30.611842 * PI() / 180) * COS(es_lat * PI() / 180) * POW(
SIN(
(
104.074666 * PI() / 180 - es_lon * PI() / 180
) / 2
),
2
)
)
) * 1000
) AS distance_um
FROM
c_ershuai
ORDER BY
distance_um ASC
但是我比较习惯使用 entity framework,于是我就想着能不能用 entity framework 实现按照距离排序。
以下是我采用的方案
首先定义一个接口,用来表示具有经纬度信息的实体。
/// <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 = * SqlFunctions.Asin(SqlFunctions.SquareRoot(Math.Pow((double)SqlFunctions.Sin(a / ), ) +
SqlFunctions.Cos(radLat1) * SqlFunctions.Cos(radLat2) * Math.Pow((double)SqlFunctions.Sin(b / ), ))) * 6378.137
let d = Math.Round((double)s * ) /
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()]
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; }
}
最后我们分页查询商店,并按照距离由近到远排序
#region 入参
double user_lng = 113.46, user_lat = 22.27; //用户经纬度
int pageIndex = ; //当前页码
int pageSize = ; //每页条数
#endregion 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 - ) * pageSize).Take(pageSize).ToList(); //分页并执行sql查询获取数据 //TODO:将查到的数据映射成DTO对象,并返回给客户端
}
好了,entity framework 实现按照距离排序 也就全部完成了。
entity framework 实现按照距离排序的更多相关文章
- Entity Framework实现多列排序
aList.OrderBy(a => a.WIndex).ThenBy(a=>a.KIndex) 类似sql:order by WIndex,KIndex
- 《Entity Framework 6 Recipes》中文翻译系列 (16) -----第三章 查询之左连接和在TPH中通过派生类排序
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 3-10应用左连接 问题 你想使用左外连接来合并两个实体的属性. 解决方案 假设你有 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (27) ------ 第五章 加载实体和导航属性之关联实体过滤、排序、执行聚合操作
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 5-9 关联实体过滤和排序 问题 你有一实体的实例,你想加载应用了过滤和排序的相关 ...
- Working with Data » Getting started with ASP.NET Core and Entity Framework Core using Visual Studio » 排序、筛选、分页以及分组
Sorting, filtering, paging, and grouping 7 of 8 people found this helpful By Tom Dykstra The Contoso ...
- MVC5 Entity Framework学习参加排序、筛选和排序功能
上一篇文章实现Student 基本的实体CRUD操作.本文将展示如何Students Index页添加排序.筛选和分页功能. 以下是排序完成时.经过筛选和分页功能截图,您可以在列标题点击排序. 1.为 ...
- ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第五章:排序、分页和路由
本章的重点是对产品信息增加排序和分页的功能,以及使用ASP.NET Routing特性添加更加友好的URL支持. 注意:如果你想按照本章的代码编写示例,你必须完成第四章或者直接从www.apress. ...
- ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第二章:利用模型类创建视图、控制器和数据库
在这一章中,我们将直接进入项目,并且为产品和分类添加一些基本的模型类.我们将在Entity Framework的代码优先模式下,利用这些模型类创建一个数据库.我们还将学习如何在代码中创建数据库上下文类 ...
- 《Entity Framework 6 Recipes》中文翻译系列 目录篇 -持续更新
为了方便大家的阅读和学习,也是响应网友的建议,在这里为这个系列做一个目录.在目录开始这前,我先来回答之前遇到的几个问题. 1.为什么要学习EF? 这个问题很简单,项目需要.这不像学校,没人强迫你学习! ...
- [ASP.NET MVC 小牛之路]06 - 使用 Entity Framework
在家闲着也是闲着,继续写我的[ASP.NET MVC 小牛之路]系列吧.在该系列的上一篇博文中,在显示书本信息列表的时候,我们是在程序代码中手工造的数据.本文将演示如何在ASP.NET MVC中使用E ...
随机推荐
- show()封装没有想象中那么简单
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- React Native开发 - 搭建React Native开发环境
移动开发以前一般都是原生的语言来开发,Android开发是用Java语言,IOS的开发是Object-C或者Swift.那么对于开发一个App,至少需要两套代码.两个团队.对于公司来说,成本还是有的. ...
- 【ODI】| 数据ETL:从零开始使用Oracle ODI完成数据集成(三)
资料库的创建.体系结构的创建.模型反向工程都已经完成了,下面就是创建以及执行接口来完成工作了. 浏览前两节请点击: [ODI]| 数据ETL:从零开始使用Oracle ODI完成数据集成(一) [OD ...
- 关于 JavaScript 中的继承
ES5 之前,继续是这样实现的 function Parent() { this.foo = function() { console.log('foo'); }; } Parent.prototyp ...
- 游戏AI之初步介绍(0)
目录 游戏AI是什么? 游戏AI和理论AI 智能的假象 (更新)游戏AI和机器学习 介绍一些游戏AI 4X游戏AI <求生之路>系列 角色扮演/沙盒游戏中的NPC 游戏AI 需要学些什么? ...
- 程序猿必知必会Linux命令之awk
前言 对于一名专业的程序员来说,Linux相关知识是必须要掌握的,其中对于文本的处理更是我们常见的操作,比如格式化输出我们需要的数据,这些数据可能会来源于文本文件或管道符,或者统计文本里面我们需要的数 ...
- 8天入门docker系列 —— 第五天 使用aspnetcore小案例熟悉容器互联和docker-compose一键部署
这一篇继续完善webnotebook,如果你读过上一篇的内容,你应该知道怎么去挂载webnotebook日志和容器的远程访问,但是这些还远不够,webnotebook 总要和一些数据库打交道吧,比如说 ...
- easyui表格自动换行
表格内容自动换行可以通过设计表格属性 nowrap:false来实现,默认值为true: 但是easyui并未提供,表头自动换行的解决方案,因为一般我们的数据表格列名都是固定的,想换行的话可以通过& ...
- Takeown、Cacls、Icacls-文件、文件夹夺权用法
常用示例如下: takeown /f 文件名 获取该文件的所属权 takeown /f /r /d n 文件夹 获取整个文件夹及其下面子目录文件的所属权 takeown /f * /a /r /d ...
- LOJ #6051. 「雅礼集训 2017 Day11」PATH
完了感觉最近留了好多坑的说,这题也是模模糊糊地会一点 首先我们发现题目要求的是单调不上升的序列个数,那么一个套路就是用值减去下标 然后考虑连续位置的限制,这个我们做一个置换然后尽量向后取 这样拿值和位 ...