能否将地理位置查询SQL语句转换为C# LINQ供.NET Web API2使用
30英里半径范围用户查询SQL转LINQ实现方案
完全可以转换为LINQ语句,适配.NET Web API2框架的常用实现如下:
1. EF6 数据库端执行方案(推荐,性能无损耗)
该方案使用EF6内置的SqlFunctions封装SQL原生函数,生成的执行SQL和你提供的原生语句逻辑完全一致,直接在数据库端执行,性能最优。
首先引入必要命名空间:
using System.Data.Entity; using System.Data.Entity.SqlServer;
对应的LINQ查询代码:
// 定义目标坐标与查询半径参数 double targetLatitude = 78.3232; double targetLongitude = 65.3234; double searchRadius = 30; // dbContext为你项目中的数据库上下文实例 var userList = dbContext.Users .Select(u => new { UserId = u.id, Distance = 3959 * SqlFunctions.Acos( SqlFunctions.Cos(SqlFunctions.Radians(targetLatitude)) * SqlFunctions.Cos(SqlFunctions.Radians(u.lat)) * SqlFunctions.Cos(SqlFunctions.Radians(u.lng) - SqlFunctions.Radians(targetLongitude)) + SqlFunctions.Sin(SqlFunctions.Radians(targetLatitude)) * SqlFunctions.Sin(SqlFunctions.Radians(u.lat)) ) }) .Where(u => u.Distance < searchRadius) .OrderBy(u => u.Distance) .ToList();
2. 内存计算方案(仅适用数据量较小的场景)
如果你需要把数据拉到本地内存后再计算,可以直接使用.NET内置的Math类实现:
// 先拉取全量用户数据 var allUsers = dbContext.Users.ToList(); // 内存计算距离筛选 var userList = allUsers .Select(u => new { UserId = u.id, Distance = 3959 * Math.Acos( Math.Cos(Math.PI * targetLatitude / 180) * Math.Cos(Math.PI * u.lat / 180) * Math.Cos(Math.PI * u.lng / 180 - Math.PI * targetLongitude / 180) + Math.Sin(Math.PI * targetLatitude / 180) * Math.Sin(Math.PI * u.lat / 180) ) }) .Where(u => u.Distance < searchRadius) .OrderBy(u => u.Distance) .ToList();
注意事项
- 需确保你的
Users实体类存在lat、lng两个数值类型字段,和数据库表字段对应 - 如果你使用的是EF Core,将
SqlFunctions替换为EF.Functions对应的内置方法即可,EF Core 3.0+已原生支持三角函数的SQL转换 - 3959为地球英里半径,如果后续需要切换为公里单位,替换为6371即可
内容的提问来源于stack exchange,提问作者JamesDeveloper
相关产品推荐
相关产品推荐

