sql >> Databasteknik >  >> RDS >> Sqlserver

Hur använder jag spatial för att söka i en radie av postnummer?

Så, med hjälp av Phils förslag, skrev jag om mycket av det här med hjälp av rumsliga ämnen. Detta fungerade utmärkt, du behöver bara .NET4.5, EF5+ och sql-server (2008 och senare tror jag). Jag använder EF6 + SQL Server 2012.

Inställning

Det första steget var att lägga till en Geography kolumnen till min databas EventListings tabell (Högerklicka på den -> Design). Jag döpte min plats:

Sedan, eftersom jag använder EDM med databasen-först, var jag tvungen att uppdatera min modell för att använda det nya fältet som jag skapade. Sedan fick jag ett felmeddelande om att jag inte kunde konvertera geografi till dubbel, så det jag gjorde för att fixa det var att välja platsegenskapen i entiteten, gå till dess egenskaper och ändra dess typ från dubbel till Geography :

Fråga inom en radie och lägga till händelser med platser

Allt du behöver göra är att fråga din enhetssamling så här:

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

Avståndsförlängningsmetoden får avståndet från det aktuella objektet, till det "andra" objektet som du skickar in. Detta andra objekt är av typen DbGeography . Du ringer bara en statisk metod och den skapar en av dessa valpar, släng sedan bara din Longitud &Latitude i den som en punkt:

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

Det är inte så jag skapade mina originCoordinates. Jag laddade ner en separat databas som hade en lista över alla postnummer och deras latituder och longituder. Jag lade till en kolumn av typen Geography till det också. Jag ska visa hur i slutet av det här svaret. Jag frågade sedan postnummerkontexten för att få ett DbGeography-objekt från fältet Plats i postnummertabellen.

Om användaren vill ha ett mer specifikt ursprung än bara ett postnummer ringer jag till Google Maps API (GeoCode för att vara mer specifik) och får latitud och longitud för användarens specifika adress via en webbtjänst, och skapar ett DBGeography-objekt från Latitude &Longitud-värdena i svaret.

Jag använder Googles API:er när jag skapar en händelse också. Jag ställer bara in platsvariabeln så här innan jag lägger till min enhet till EF:

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

Andra tips och tricks och felsökning

Hur fick jag metoden för distansförlängning?

För att få tilläggsmetoden Distance du måste lägga till en referens till ditt projekt:System.Data.Entity När du har gjort det måste du lägga till med:using System.Data.Entity.Spatial; till din klass.

Distance förlängningsmetoden returnerar avståndet med en måttenhet meter (Du kan ändra det tror jag, men det här är standard). Här var min radieparameter i miles så jag gjorde lite matematik för att konvertera.

Obs :Det finns en DBGeography klass i System.Data.Spatial . Det här är fel och det skulle inte fungera för mig. Många exempel jag hittade på internet använde den här.

Hur man konverterar Lat/Long till Geografikolumn

Så, om du var som jag och laddade ner en postnummerdatabas med alla Latitude &Longitude kolumner och insåg sedan att det inte hade en Geografi-kolumn... det här kan hjälpa:

1) Lägg till en platskolumn i tabellen. Ställ in typen på Geografi.

2) Kör följande sql

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

Så här visar du detaljerna för ett geografiobjekt

Så när du frågar din EventListings-tabell i SQL Server Management Studio efter att du har infogat några DbGeography-objekt, ser du Location kolumnen innehåller ett hexadecimalt värde som:0x1234513462346. Detta är inte särskilt användbart när du vill försäkra dig om att de korrekta värdena har infogats.

För att faktiskt se latitud och longitud utanför detta fält måste du fråga det så här:

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



  1. Mysql-fråga kontrollera blob-kolumnen typ i where-satsen

  2. Så här klusterar du dina ProxySQL-lastbalanserare

  3. Felkod:1005. Kan inte skapa tabellen '...' (felnr:150)

  4. Varför exekveringstiden för lagrad oracle-procedur ökar kraftigt beroende på hur den exekveras?