2013-05-03 9 views
5

vogliamo ricevere la lista dei luoghi vicini dal database utilizzando LINQ in ASP.NET 2012 e vorrebbe un feedback sulla nostra strategia.Utilizzando LINQ trovare luoghi vicini dal database


Il mio tavolo e dati falsi:

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

1) Nel nostro progetto la posizione attuale del client (latitudine e longitudine) è preso come input

2) Al lato server, a seconda della la posizione corrente del cliente, abbiamo bisogno di trovare luoghi vicini dal database utilizzando LINQ

Ecco il codice per SQL che ho già usato, ma ora vogliamo usare 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 

[Ma la domanda è come scrivere una tale query in LINQ.]

Il mio lavoro su questo:

Durante la ricerca di una soluzione, mi sono imbattuto in questo codice

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

Ma il problema è, come fare riferimento a ConversionHelper o sotto quale spazio dei nomi viene.

Tutto consiglio è apprezzato.

+1

Perché non utilizzare una stored procedure? Puoi mappare il risultato di un processo memorizzato su un oggetto nello stesso modo in cui mapperesti una tabella, ad es. getClosePlaces_Result. –

+0

Spiacente, dovrei ricordare che è possibile specificare che il tipo restituito è un elenco di posizioni, se questo è ciò che si desidera. –

+0

@JuannStrauss a parte le ovvie conseguenze sulla dipendenza del codice, l'OP sta chiedendo come farlo in C# ;-) –

risposta

2

Ecco il codice che alla fine ho da stabilirsi con

1) Create una classe, dicono

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) quindi includere il codice qui sotto in qualsiasi file che si desidera, dicono

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

Ha funzionato per me, spero che vi aiuterà a.

4

quindi, se tutto ciò che si desidera è calcolare la distanza tra due coordinate, perché non utilizzare Dot Net GeoCoordinate?

va qualcosa come

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

double distance = firstCordinate.GetDistanceTo(secondCordinate); 

si può trovare all'interno dello spazio dei nomi System.Device.Location.

Quindi questo ti farà risparmiare da tutti quelli Math.Cos e Math.Sin e il tuo linq sarà chiaro e semplice. (Probabilmente un ciclo foreach farà)

così la vostra intera query possono essere riassunti come:

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 
} 
Problemi correlati