sql >> Database >  >> RDS >> Sqlserver

Hoe gebruik ik ruimtelijke gegevens om in een straal van postcodes te zoeken?

Dus, gebruikmakend van de suggestie van Phil, heb ik veel hiervan herschreven met behulp van ruimtelijke gegevens. Dit werkte prima, je hebt alleen .NET4.5, EF5+ en sql-server nodig (2008 en hoger geloof ik). Ik gebruik EF6 + SQL Server 2012.

Configuratie

De eerste stap was het toevoegen van een Geography kolom naar mijn database EventListings tabel (klik er met de rechtermuisknop op -> Ontwerp). Ik noemde de mijne Locatie:

Vervolgens, aangezien ik de EDM eerst met database gebruik, moest ik mijn model bijwerken om het nieuwe veld te gebruiken dat ik heb gemaakt. Toen kreeg ik een foutmelding over het niet kunnen converteren van geografie naar dubbel, dus wat ik deed om het op te lossen, was de locatie-eigenschap in de entiteit selecteren, naar de eigenschappen gaan en het type wijzigen van dubbel in Geography :

Query binnen een straal en evenementen toevoegen met locaties

Het enige wat u hoeft te doen, is uw entiteitsverzameling als volgt opvragen:

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

De Distance extension-methode haalt de afstand van het huidige object naar het "andere" object dat u doorgeeft. Dit andere object is van het type DbGeography . Je roept gewoon een statische methode aan en het creëert een van deze puppy's, gooi dan gewoon je lengte- en breedtegraad erin als een punt:

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

Dit is niet hoe ik mijn originCoordinates heb gemaakt. Ik heb een aparte database gedownload met een lijst van alle postcodes en hun breedte- en lengtegraden. Ik heb een kolom van het type Geography toegevoegd daar ook naar. Ik zal laten zien hoe aan het einde van dit antwoord. Vervolgens heb ik de postcodecontext opgevraagd om een ​​DbGeography-object te krijgen uit het veld Location in de ZipCode-tabel.

Als de gebruiker een meer specifieke oorsprong wil dan alleen een postcode, bel ik de Google Maps API (GeoCode om specifieker te zijn) en krijg ik de breedte- en lengtegraad voor het specifieke adres van de gebruiker via een webservice en maak ik een DBGeography-object van de breedte- en lengtegraadwaarden in het antwoord.

Ik gebruik ook Google API's wanneer ik een evenement maak. Ik heb de locatievariabele zo ingesteld voordat ik mijn entiteit aan EF toevoeg:

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

Andere tips en trucs en probleemoplossing

Hoe ben ik aan de Distance Extension-methode gekomen?

Om de extensiemethode Distance te krijgen u moet een verwijzing naar uw project toevoegen:System.Data.Entity Nadat je dat hebt gedaan, moet je het gebruik toevoegen:using System.Data.Entity.Spatial; naar je klas.

De Distance extension method retourneert de afstand met een maateenheid (Je kunt het veranderen denk ik, maar dit is standaard). Hier was mijn straalparameter in mijlen, dus ik heb wat rekenwerk gedaan om te converteren.

Opmerking :Er is een DBGeography klasse in System.Data.Spatial . Dit is de verkeerde en bij mij zou het niet werken. Veel voorbeelden die ik op internet vond, gebruikten deze.

Lat/Long converteren naar geografiekolom

Dus, als je net als ik was en een postcodedatabase downloadde met alle Latitude &Longitude kolommen, en realiseerde zich toen dat het geen kolom Aardrijkskunde had... dit zou kunnen helpen:

1) Voeg een kolom Locatie toe aan uw tabel. Stel het type in op Geografie.

2) Voer de volgende sql uit

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

De details van een geografie-item bekijken

Dus wanneer u uw EventListings-tabel opvraagt ​​in Sql Server Management Studio nadat u enkele DbGeography-items heeft ingevoegd, ziet u de Location kolom bevat een hexadecimale waarde zoals:0x1234513462346. Dit is niet erg handig als u er zeker van wilt zijn dat de juiste waarden zijn ingevoegd.

Om de breedte- en lengtegraad daadwerkelijk buiten dit veld te bekijken, moet u het als volgt opvragen:

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



  1. dblink bestaat niet, ook al bestaat de extensie al?

  2. Hoe bewerk ik een tabel om CASCADE DELETE in te schakelen?

  3. Een relatie maken tussen tabel en weergave in het Entity Framework

  4. DateTime::CreateFromFormat voor PHP 5.2.14