sql >> Database teknologi >  >> RDS >> Sqlserver

Hvordan bruger jeg spatials til at søge i en radius af postnumre?

Så ved at bruge Phils forslag, omskrev jeg meget af dette ved hjælp af rumlige elementer. Dette fungerede godt, du skal bare bruge .NET4.5, EF5+ og sql server (2008 og derover, tror jeg). Jeg bruger EF6 + SQL Server 2012.

Opsætning

Det første skridt var at tilføje en Geography kolonne til min database EventListings tabel (Højreklik på den -> Design). Jeg navngav min placering:

Dernæst, da jeg bruger EDM med database-first, var jeg nødt til at opdatere min model for at bruge det nye felt, som jeg oprettede. Så modtog jeg en fejl om, at jeg ikke kunne konvertere Geography til double, så det, jeg gjorde for at rette det, var at vælge Location-egenskaben i entiteten, gå til dens egenskaber og ændre dens type fra double til Geography :

Forespørgsel inden for en radius og tilføjelse af begivenheder med placeringer

Så skal du bare forespørge på din enhedssamling på denne måde:

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

Afstandsudvidelsesmetoden henter afstanden fra det aktuelle objekt til det "andet" objekt, som du passerer ind. Dette andet objekt er af typen DbGeography . Du kalder bare en statisk metode, og den skaber en af ​​disse hvalpe, så smid bare din længde- og breddegrad i den som et punkt:

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

Det er ikke sådan, jeg oprettede mine originCoordinates. Jeg downloadede en separat database, der havde en liste over alle postnumre og deres breddegrader og længdegrader. Jeg tilføjede en kolonne af typen Geography også til det. Jeg viser hvordan i slutningen af ​​dette svar. Jeg forespurgte derefter postnummerkonteksten for at få et DbGeography-objekt fra feltet Placering i postkodetabellen.

Hvis brugeren ønsker en mere specifik oprindelse end blot et postnummer, ringer jeg til Google Maps API (GeoCode for at være mere specifik) og får bredde- og længdegraden for brugerens specifikke adresse via en webservice, og opretter et DBGeography objekt fra værdierne for breddegrad og længdegrad i svaret.

Jeg bruger også Google API'er, når jeg opretter en begivenhed. Jeg indstillede bare placeringsvariablen sådan her, før jeg tilføjede min enhed til EF:

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

Andre tips og tricks og fejlfinding

Hvordan fik jeg metoden til afstandsforlængelse?

For at få udvidelsesmetoden Distance du skal tilføje en reference til dit projekt:System.Data.Entity Når du har gjort det, skal du tilføje ved hjælp af:using System.Data.Entity.Spatial; til din klasse.

Distance forlængelsesmetoden returnerer afstanden med en måleenhed meter (Du kan ændre det tror jeg, men dette er standard). Her var min radiusparameter i miles, så jeg lavede noget matematik for at konvertere.

Bemærk :Der er en DBGeography klasse i System.Data.Spatial . Dette er den forkerte og det ville ikke virke for mig. Mange eksempler, jeg fandt på internettet, brugte denne.

Sådan konverteres Lat/Long til Geografi-kolonne

Så hvis du var ligesom mig og downloadede en postnummerdatabase med alle Latitude &Longitude kolonner, og indså så, at den ikke havde en Geografi-kolonne... dette kunne måske hjælpe:

1) Tilføj en placeringskolonne til din tabel. Indstil typen til Geografi.

2) Udfør følgende sql

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

Sådan får du vist detaljerne for et geografielement

Så når du forespørger på din EventListings-tabel i SQL Server Management Studio, efter at du har indsat nogle DbGeography-elementer, vil du se Location kolonne indeholder en hex-værdi som:0x1234513462346. Dette er ikke særlig nyttigt, når du vil sikre dig, at de korrekte værdier er indsat.

For faktisk at se bredde- og længdegraden ud af dette felt skal du forespørge på det sådan:

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



  1. Heltal vs char for DB record egenskab

  2. Ret fejl "ORA-01790:udtryk skal have samme datatype som tilsvarende udtryk"

  3. Hadoop og MySQL integration

  4. Konverter en UTC-tidszone i postgresql til EST (lokal tid)