Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Wie verwende ich Spatials, um einen Umkreis von Postleitzahlen zu suchen?

Also, mit Phils Vorschlag, habe ich viel davon mit Spatials neu geschrieben. Das hat super geklappt, man braucht nur .NET4.5, EF5+ und SQL Server (2008 und höher glaube ich). Ich verwende EF6 + Sql Server 2012.

Einrichtung

Der erste Schritt bestand darin, eine Geography hinzuzufügen Spalte zu meiner Datenbank EventListings Tabelle (Rechtsklick darauf -> Design). Ich habe meinen Ort benannt:

Als nächstes musste ich, da ich das EDM zuerst mit der Datenbank verwende, mein Modell aktualisieren, um das neue Feld zu verwenden, das ich erstellt habe. Dann erhielt ich eine Fehlermeldung, dass Geographie nicht in Double konvertiert werden konnte. Um das Problem zu beheben, wählte ich die Location-Eigenschaft in der Entität aus, wechselte zu ihren Eigenschaften und änderte ihren Typ von Double in Geography :

Abfragen innerhalb eines Umkreises und Hinzufügen von Ereignissen mit Standorten

Dann müssen Sie nur noch Ihre Entitätssammlung wie folgt abfragen:

 var events = EventRepository.EventListings
                             .Where(x => x.Location.Distance(originCoordinates) * 0.00062 <= radiusParam); 

Die Entfernungserweiterungsmethode ruft die Entfernung vom aktuellen Objekt zum „anderen“ Objekt ab, das Sie übergeben. Dieses andere Objekt ist vom Typ DbGeography . Sie rufen einfach eine statische Methode auf und sie erstellt einen dieser Welpen, dann werfen Sie einfach Ihren Längen- und Breitengrad als Punkt hinein:

DBGeography originCoordinates = DBGeography.fromText("Point(" + originLongitude + " " + originLatitude + ")");

So habe ich meine originCoordinates nicht erstellt. Ich habe eine separate Datenbank heruntergeladen, die eine Liste aller Postleitzahlen und ihrer Längen- und Breitengrade enthielt. Ich habe eine Spalte vom Typ Geography hinzugefügt auch dazu. Ich werde zeigen, wie am Ende dieser Antwort. Dann habe ich den Kontext der Postleitzahl abgefragt, um ein DbGeography-Objekt aus dem Feld Location in der Tabelle ZipCode abzurufen.

Wenn der Benutzer einen spezifischeren Ursprung als nur eine Postleitzahl wünscht, rufe ich die Google Maps-API (GeoCode, um genauer zu sein) auf und erhalte den Breiten- und Längengrad für die spezifische Adresse des Benutzers über einen Webservice und erstelle ein DBGeography-Objekt aus die Breiten- und Längenwerte in der Antwort.

Ich verwende auch Google APIs, wenn ich ein Ereignis erstelle. Ich setze einfach die Standortvariable wie folgt, bevor ich meine Entität zu EF hinzufüge:

someEventEntity.Location = DBGeography.fromText("Point(" + longitudeFromGoogle+ " " + latitudeFromGoogle + ")");

Weitere Tipps &Tricks &Fehlerbehebung

Wie habe ich die Distanzerweiterungsmethode erhalten?

So erhalten Sie die Erweiterungsmethode Distance Sie müssen Ihrem Projekt einen Verweis hinzufügen:System.Data.Entity Danach müssen Sie Folgendes hinzufügen:using System.Data.Entity.Spatial; zu deiner Klasse.

Die Distance -Erweiterungsmethode gibt die Entfernung mit einer Maßeinheit von Metern zurück (Sie können es ändern, denke ich, aber das ist die Standardeinstellung). Hier war mein Radius-Parameter in Meilen, also habe ich ein wenig nachgerechnet, um ihn umzurechnen.

Hinweis :Es gibt eine DBGeography Klasse in System.Data.Spatial . Das ist die falsche und es würde bei mir nicht funktionieren. Viele Beispiele, die ich im Internet gefunden habe, verwenden dieses.

So konvertieren Sie Lat/Long in die geografische Spalte

Also, wenn Sie wie ich wären und eine Postleitzahl-Datenbank mit allen Latitude herunterladen würden &Longitude Spalten und stellte dann fest, dass es keine Geografie-Spalte gab ... das könnte helfen:

1) Fügen Sie Ihrer Tabelle eine Standortspalte hinzu. Stellen Sie den Typ auf Geografie ein.

2) Führen Sie die folgende SQL aus

UPDATE [ZipCodes]
SET Location = geography::STPointFromText('POINT(' + CAST([Longitude] AS VARCHAR(20)) + ' ' + CAST([Latitude] AS VARCHAR(20)) + ')', 4326)

So zeigen Sie die Details eines geografischen Elements an

Wenn Sie also Ihre EventListings-Tabelle in Sql Server Management Studio abfragen, nachdem Sie einige DbGeography-Elemente eingefügt haben, sehen Sie den Location Spalte enthält einen Hex-Wert wie:0x1234513462346. Dies ist nicht sehr hilfreich, wenn Sie sicherstellen möchten, dass die richtigen Werte eingefügt wurden.

Um tatsächlich den Breiten- und Längengrad dieses Felds anzuzeigen, müssen Sie es wie folgt abfragen:

SELECT Location.Lat Latitude, Location.Long Longitude
FROM [EventListings]