【问题标题】:Using LINQ find nearby places from database使用 LINQ 从数据库中查找附近的地方
【发布时间】:2013-05-03 10:01:05
【问题描述】:

我们希望在 ASP.NET 2012 中使用 LINQ 从数据库中接收附近地点的列表,并希望对我们的策略提供一些反馈。


我的表格和假数据:

     PlaceId    Name       Latitude   Longitude 
       1          A          18.1        20.1
       2          B          18.2        20.2
       3          C          18.3        20.3

1) 在我们的项目中,客户端当前位置(经纬度)作为输入

2) 在服务器端,根据客户端当前位置,我们需要使用 LINQ 从数据库中查找附近的地方

这是我之前使用的 SQL 代码,但现在我们要使用 LINQ。

SELECT  name, Latitude, Longitude , 
  ( 3959 * acos( cos( radians(?) )* cos( radians( Latitude) ) * cos( radians( Longitude ) - radians(?) ) 
 + sin( radians(?) ) * sin( radians( Latitude) ) ) ) AS distance 
FROM TABLE_NAME 
HAVING distance < ? 
ORDER BY distance LIMIT 0 , 20

[但问题是如何在 LINQ 中编写这样的查询。]

我在这方面的工作:

在寻找解决方案时,我遇到了这段代码

        var Value1 = 57.2957795130823D;
        var Value2 = 3958.75586574D;

        var searchWithin = 20;

    double latitude = ConversionHelper.SafeConvertToDoubleCultureInd(Latitude, 0),
          longitude = ConversionHelper.SafeConvertToDoubleCultureInd(Longitude, 0);

    var location = (from l in sdbml.Places
                    let temp = Math.Sin(Convert.ToDouble(l.Latitude) / Value1) *  Math.Sin(Convert.ToDouble(latitude) / Value1) +
                             Math.Cos(Convert.ToDouble(l.Latitude) / Value1) *
                             Math.Cos(Convert.ToDouble(latitude) / Value1) *
                             Math.Cos((Convert.ToDouble(longitude) / Value1) - (Convert.ToDouble(l.Longitude) / Value1))
                         let calMiles = (Value2 * Math.Acos(temp > 1 ? 1 : (temp < -1 ? -1 : temp)))
                         where (l.Latitude > 0 && l.Longitude > 0)
                         orderby calMiles
                        select new location
                             {
                                    Name = l.name
                                });
                        return location .ToList();

但问题是,如何引用 ConversionHelper 或它来自哪个命名空间。

感谢所有建议。

【问题讨论】:

  • 为什么不使用存储过程呢?您可以将存储过程的结果映射到对象,其方式与映射表的方式非常相似,例如getClosePlaces_Result.
  • 对不起,我应该提一下,如果你想要的话,你可以指定返回类型是位置列表。
  • @JuannStrauss 除了明显的代码依赖后果外,OP 正在请求如何在 C# 中执行此操作 ;-)
  • 这就是我添加评论而不是回答的原因。

标签: asp.net .net linq c#-4.0 sql-to-linq-conversion


【解决方案1】:

所以,如果您只想计算两个坐标之间的距离,为什么不使用 Dot Net 的 GeoCoordinate

类似

 var firstCordinate = new GeoCoordinate(latitude1, longitude1);
 var secondCordinate = new GeoCoordinate(latitude2, longitude2);

 double distance = firstCordinate.GetDistanceTo(secondCordinate);

你可以在命名空间System.Device.Location中找到它。

因此,这将使您摆脱所有 Math.CosMath.Sin 的困扰,并且您的 linq 将变得简单明了。 (可能一个 foreach 循环就可以了)

所以你的整个查询可以总结为:

List<Location> locations = new List<Location>();
foreach(var place in sdbml.Places)
{
   //your logic to compare various place's co-ordinates with that of
   //user's current co-ordinate
}

【讨论】:

    【解决方案2】:

    这是最后我必须解决的代码

    1)创建一个类,比如说

    DistanceModel.cs

    public class DistanceModel
    {
       public int PlaceId { get; set; }
    
       public string Name { get; set; }
    
       public double Latitute { get; set; }
    
       public double Longitude { get; set; }
    
    } 
    

    2)然后在您想要的任何文件中包含以下代码,比如

    MainPage.cs

         /*Call GetAllNearestFamousPlaces() method to get list of nearby places depending 
          upon user current location.
          Note: GetAllNearestFamousPlaces() method takes 2 parameters as input
         that is GetAllNearestFamousPlaces(user_current_Latitude,user_current_Longitude) */
    
    
       public void GetAllNearestFamousPlaces(double currentLatitude,double currentLongitude)
        {
            List<DistanceModel> Caldistance = new List<DistanceModel>();
            var query = (from c in sdbml.Places
                         select c).ToList();
            foreach (var place in query)
            {
                double distance = Distance(currentLatitude, currentLongitude, place.Latitude, place.Logitude);
                if (distance < 25)          //nearbyplaces which are within 25 kms 
                {
                    DistanceModel dist = new DistanceModel();
                    dist.Name = place.PlaceName;
                    dist.Latitute = place.Latitude;
                    dist.Longitude = place.Logitude;
                    dist.PlaceId = place.PlaceId;
                    Caldistance.Add(getDiff);
                }
            }                      
        }
    
       private double Distance(double lat1, double lon1, double lat2, double lon2)
        {
            double theta = lon1 - lon2;
            double dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta));
            dist = Math.Acos(dist);
            dist = rad2deg(dist);
            dist = (dist * 60 * 1.1515) / 0.6213711922;          //miles to kms
            return (dist);
        }
    
       private double deg2rad(double deg)
        {
            return (deg * Math.PI / 180.0);
        }
    
       private double rad2deg(double rad)
        {
            return (rad * 180.0 / Math.PI);
        }
    

    它对我有用,希望它能帮助你。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-19
      • 2017-05-12
      • 2018-09-06
      • 1970-01-01
      • 2013-06-27
      • 1970-01-01
      相关资源
      最近更新 更多