2013-05-03 55 views
5

我們希望在ASP.NET 2012中使用LINQ接收來自數據庫附近地點的列表,並希望獲得關於我們策略的一些反饋。使用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或根據該命名空間而來。

所有建議表示讚賞。

+1

爲什麼不使用存儲過程?您可以將存儲的proc的結果映射到對象,這與您要映射表的方式非常相似,例如, getClosePlaces_Result。 – 2013-05-03 10:18:46

+0

對不起,我應該提到,你可以指定返回類型是位置列表,如果這是你想要的。 – 2013-05-03 10:21:45

+0

@JuannStrauss除了明顯的代碼依賴性後果之外,OP請求如何在C#中執行此操作;-) – 2013-05-03 11:43:36

回答

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); 
    } 

它爲我工作,希望它會幫助你。

4

所以,如果你想要的是計算兩個座標之間的距離,爲什麼不使用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 
}