2013-05-03 8 views
5

Wir möchten eine Liste der Orte in der Nähe von der Datenbank mit LINQ in ASP.NET 2012 erhalten und möchten ein Feedback zu unserer Strategie.Verwenden von LINQ Suchen Sie Orte in der Nähe aus der Datenbank


Mein Tisch und gefälschte Daten:

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

1) In unserem Projekt des Client aktuelle Standort (Breitengrad und Längengrad) als Eingabe genommen Bei der Server-Seite

2), in Abhängigkeit von der aktuelle Standort des Clients, müssen wir in der Nähe von der Datenbank mit LINQ

Finden Sie den Code für SQL, die ich früher verwendet, aber jetzt wollen wir LINQ verwenden.

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 

[Aber die Frage ist, wie eine solche Abfrage in LINQ zu schreiben.]

Meine Arbeit auf diesem:

Während für die Lösung suchen, stieß ich auf diesem Code

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

Aber das Problem ist, wie Referenz ConversionHelper oder unter welchen Namespace es kommt.

Alle Ratschläge sind willkommen.

+1

Warum nicht eine gespeicherte Prozedur verwenden? Sie können das Ergebnis eines gespeicherten Proc einem Objekt auf die gleiche Weise zuordnen, wie Sie eine Tabelle zuordnen würden, z. getClosePlaces_Result. –

+0

Entschuldigung, ich sollte erwähnen, dass Sie angeben können, dass der Rückgabetyp eine Liste von Standorten ist, wenn Sie das möchten. –

+0

@JuannStrauss abgesehen von offensichtlichen Auswirkungen auf die Codeabhängigkeit, fragt das OP, wie man das in C# macht ;-) –

Antwort

2

Hier ist der Code, der schließlich muss ich sesshaft mit

1) Erstellen eine Klasse, sagen

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) Dann sind der folgenden Code in welcher auch immer Datei, die Sie wollen, sagt

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

Es funktionierte für mich, hoffen, es wird Ihnen helfen, zu.

4

also, wenn alles, was Sie wollen, ist Abstand zwischen zwei Koordinaten zu berechnen, warum verwenden Sie nicht Dot Net GeoCoordinate?

es geht so etwas wie

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

double distance = firstCordinate.GetDistanceTo(secondCordinate); 

Sie es innerhalb Namespace System.Device.Location finden.

So wird Sie von all diesen Math.Cos und Math.Sin speichern und Ihre LINQ wird einfach und klar sein. (Wahrscheinlich eine foreach-Schleife tun wird)

so Ihre gesamte Abfrage wie folgt zusammengefasst werden können:

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 
}