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

Er det muligt at bruge SqlGeography med Linq til Sql?

Hvis alt du vil med SqlGeography er at spore point og udnytte SQL Server 2008's rumlige indekser, kan du, som andre har bemærket, skjule din geodatakolonne fra Linq til SQL og bruge UDF'er eller lagrede procedurer. Antag, at du har en tabel AddressFields, der inkluderer felter for breddegrad og længdegrad. Tilføj denne tabel til din DBML-fil, og skriv en hvilken som helst kode, som du ønsker, der angiver felterne Latitude og Longitude. Derefter tilføjer SQL-koden nedenfor et Geo geogarphy-felt til den tabel og skaber en trigger i databasen, der automatisk indstiller Geo-feltet baseret på felterne Latitude og Longitude. I mellemtiden opretter koden nedenfor også andre nyttige UDF'er og lagrede procedurer:DistanceBetween2 (jeg havde allerede en DistanceBetween) returnerer afstanden mellem adressen repræsenteret i et AddressField og et specificeret latitude/longitude-par; DistanceWithin returnerer forskellige felter fra alle Address Fields inden for en specificeret mileafstand; UDFDistanceWithin gør det samme som en brugerdefineret funktion (nyttigt hvis du vil indlejre dette i en større forespørgsel); og UDFNearestNeighbors returnerer felter fra AddressField svarende til det specificerede antal naboer nærmest et bestemt punkt. (En grund til at bruge UDFNearestNeighbors er, at SQL Server 2008 ikke vil optimere sin brug af et rumligt indeks, hvis du bare kalder ordre ved at kalde DistanceBetween2.)

Du bliver nødt til at tilpasse dette ved at ændre AddressFields til din tabel og tilpasse felterne fra den tabel, som du vil have returneret (se i koden omkring referencer til AddressFieldID). Du kan derefter køre dette på din database og kopiere de resulterende lagrede procedurer og UDF'er til din DBML, og derefter kan du bruge dem i forespørgsler. Samlet set giver dette dig ret nemt at drage fordel af et rumligt indeks over point.

------------------------------------------------- ----------------------------------------------------

--[1]

--INITIAL AUDITselect * fra dbo.AddressFieldsGO--ADD COLUMN GEOIF EXISTS (VÆLG navn FRA sysindexes WHERE name ='SIndx_AddressFields_geo')DROP INDEX SIndx_AddressFields_geo ON AddressnameISTROMs SELECT b.EXFelter GOIF (b.SykkenavnFieldsGOIF, b.SykkenavnFieldsGOIF) HVOR a.id =b.id og a.name ='AddressFields' og b.name ='Geo' og a.type ='U' ) ÆNDRINGSTABEL Adressefelter DROP KOLONNE GeoGOalter tabel AddressFields tilføjer Geo geografi 

--[2]

--SET GEO VALUEGOUPDATE AddressFieldsSET Geo =geography::STPointFromText('POINT(' + CAST([Længdegrad] AS VARCHAR(20)) + ' ' + CAST([Latitude] AS VARCHAR(20)) + ')', 4326) 

--[3] OPRET INDEKS

HVIS EKSISTERER (VÆLG navn FRA sysindexes WHERE navn ='SIndx_AddressFields_geo')DROP INDEX SIndx_AddressFields_geo ON AddressFieldsGOCREATE SPATIAL INDEX SIndx_AddressFields_geo ON AddressUPDATEFields-AdresseFelds-Adresse-DatoFields-Adresse-Dato.Felds-Adresse-dato-dato.-Adresse-dato-dato-dato.> 

--[4] OPRET PROCEDURE USP_SET_GEO_VALUE PARA 1 LATITUDE 2 LONGITUDE

HVIS FINNES (VÆLG navn FRA sysobjects WHERE navn ='USPSetGEOValue' OG type ='P') SLIP PROC USPSetGEOValueGOGOCREATE PROC USPSetGEOValue @latitude decimal(18,8), @longitude decimal(18,8)SOM OPDATERING AddressFields SET Geo =geografi::STPointFromText('POINT(' + CAST(@longitude AS VARCHAR(20)) + ' ' + CAST(@latitude AS VARCHAR(20)) + ')', 4326) WHERE [Længdegrad] eksempel @sqldat.com og [Latitude] =@latitudeGO--TESTEXEC USPSetGEOValue 38.87350500,-76.97627500GO 

--[5] OPRET TRIGGER PÅ LAT/LANG VÆRDIÆNDRING/INSERT ---> INDSTIL GEOCODE

HVIS FINDER (VÆLG navn FRA sysobjects WHERE navn ='TRGSetGEOCode' OG type ='TR')DROP TRIGGER TRGSetGEOCodeGOCREATE TRIGGER TRGSetGEOCode PÅ adressefelter EFTER INSERT,OPDATERINGER DECLARE @latitude decimal),(18, decimal) 18,8) HVIS ( OPDATERING (Breddegrad) ELLER OPDATERING (Længdegrad) ) BEGIN VÆLG @latitude =breddegrad ,@longitude =længdegrad fra indsat OPDATERING Adressefelter SET Geo =geografi::STPointFromText('POINT(' + CAST(@longitude AS VARCHAR) (20)) + ' ' + CAST(@latitude SOM VARCHAR(20)) + ')', 4326) HVOR [Longitude] [email protected] og [Latitude] =@latitude END ELSE BEGIN SELECT @latitude =latitude , @longitude =længdegrad fra indsat OPDATERING Adressefelter SET Geo =geografi::STPointFromText('POINT(' + CAST(@longitude AS VARCHAR(20)) + ' ' + CAST(@latitude AS VARCHAR(20)) + ')', 4326) HVOR [Longitu de] [email protected] og [Latitude] =@latitude END GO 

--[6] OPRET PROC USP_SET_GEO_VALUE_INITIAL_LOAD ----> KUN EN GANG

HVIS FINDER (VÆLG navn FRA sysobjects WHERE navn ='USPSetAllGeo' OG type ='P') DROP PROC USPSetAllGeoGOCREATE PROC USPSetAllGeoASUPDATE AddressFieldsSET Geo =geografi::STPointFromText('POINTLong(' + CAST] AS VARCHAR(20)) + ' ' + CAST([Latitude] AS VARCHAR(20)) + ')', 4326)GO 

--[7] EKSISTERENDE PROC DistanceBetween, som returnerer afstanden mellem to specificerede punkter

--efter bredde/længde-koordinatpar. --ALTER PROC DistanceBetween2

HVIS FINDER (VÆLG navn FRA sysobjects WHERE navn ='AfstandBetween2' OG type ='FN')DROP FUNKTION AfstandMellem2GOCREATE FUNKTION [dbo].[AfstandBetween2] (@AddressFieldID som int, @Lat1 som reel,@Long1 som reel som ægte)RETURNERER realASBEGIN DECLARE @KMperNM float =1,0/1,852; DECLARE @nwi geography =(vælg geo fra adressefelter, hvor AddressFieldID =@AddressFieldID) DECLARE @edi geography =geography::STPointFromText('POINT(' + CAST(@Long1 AS VARCHAR(20)) + ' ' + CAST(@Lat1 AS VARCHAR(20)) + ')', 4326) DECLARE @dDistance som reel =(SELECT (@nwi.STDistance(@edi)/1000.0) * @KMperNM) return (@dDistance); SLUT 

GÅ--TEST

Distance Between2 12159,40.75889600,-73.99228900

--[8] OPRET PROCEDURE USPDistanceWithin

-- RETURNERER LISTE OVER ADRESSER FRA Address Fields-tabellen

HVIS FINDER (VÆLG navn FRA sysobjects WHERE navn ='USPDistanceWithin' OG type ='P') SLIPPROCEDURE USPDistanceWithin

GOCREATE PROCEDURE [dbo].USPDistanceWithin (@lat som reel,@lang som reel, @distance som float)ASBEGIN DECLARE @edi geography =geography::STPointFromText('POINT(' + CAST(@Long AS VARCHAR(20)) + ' ' + CAST(@Lat AS VARCHAR(20)) + ')', 4326) SET @distance =@distance * 1609.344 -- konverter afstand til meter vælg AddressFieldID ,FieldID ,AddressString ,Latitude ,Længdegrad ,LastGeocode ,Status --,Geo fra AddressFields a WITH(INDEX(SIndx_AddressFields_geo)) hvor a.geo.STDistance(@edi) <=@Distance END 

--TEST

--inden for 3 milesUSPDistanceInden for 38.90606200,-76.92943500,3GO--inden for 5 milesUSPDistanceIndenfor 38.90606200,-76.92943500,5GO--inden for 10 milesUSPDistance 38.90606200,5GO--inden for 10 mileUSPDistance 38.906,06,906,901,38.906.

--[9] OPRET FUNKTION FNDistanceWithin

-- RETURNERER LISTE OVER ADRESSER FRA Address Fields-tabellen

HVIS EKSISTERER (VÆLG navn FRA sysobjects WHERE navn ='UDFDistanceWithin' OG type ='TF')DROP FUNKTION UDFDistanceWithin

GOCREATE FUNCTION UDFDistanceWithin (@lat som reel,@lang som reel, @distance som reel)RETURNER @AddressIdsToReturn TABLE ( AddressFieldID INT ,FieldID INT )ASBEGIN DECLARE @edi geography =geography::STPointFromText('POINT( ' + CAST(@Long AS VARCHAR(20)) + ' ' + CAST(@Lat AS VARCHAR(20)) + ')', 4326) SET @distance =@distance * 1609.344 -- konverter afstand til meter INSERT INTO @ AddressIdsToReturn vælg AddressFieldID ,FieldID from AddressFields a WITH(INDEX(SIndx_AddressFields_geo)) hvor a.geo.STDistance(@edi) <=@Distance RETURN END 

--TEST

--indenfor 3 milesselect * fra UDFDistanceWithin(38.90606200,-76.92943500,3)GO--inden for 5 milesselect * fra UDFDistanceWithin( 38.90606200,-76.92943500,5)GO-3tf.in 06.06.06.92943500,5) 06.92943500.

--[9] OPRET FUNKTION UDFNearestNeighbors

-- RETURNERER LISTE OVER ADRESSER FRA Address Fields-tabellen

HVIS FINDER (VÆLG navn FRA sysobjects WHERE navn ='UDFNearestNeighbors' OG type ='TF')DROP FUNKTION UDFNearestNeighbors

GO 

HVIS FINNES (VÆLG navn FRA sysobjects HVOR navn ='tal' OG xtype ='u') SLIP TABEL-numre

GO-- Opret først en taltabel, som vi vil bruge nedenfor.VÆLG TOP 100000 IDENTITET(int,1,1) SOM n INTO tal FRA MASTER..spt_values ​​a, MASTER..spt_values ​​b OPRET UNIK CLUSTERED INDEX idx_1 ON numbers(n)GOCREATE FUNCTION UDFNearestNeighbors (@lat as real,@long as real, @neighbors as int)RETURNS @AddressIdsToReturn TABLE ( AddressFieldID INT ,FieldID INT )ASBEGIN geografiPunkt:iT geografiPunkt:'ex POINT(' + CAST(@Long AS VARCHAR(20)) + ' ' + CAST(@Lat AS VARCHAR(20)) + ')', 4326) DECLARE @start FLOAT =1000; WITH NearestPoints AS ( SELECT TOP(@neighbors) WITH TIES *, AddressFields.geo.STDistance(@edi) AS dist FROM Numbers JOIN AddressFields WITH(INDEX(SIndx_AddressFields_geo)) ON AddressFields.geo.STDistance) <( POWER(2,Numbers.n) ORDER BY n ) INSERT INTO @AddressIdsToReturn SELECT TOP(@naboer) AddressFieldID ,FieldID FROM NearestPoints ORDER BY n DESC, dist RETURN END 

--TEST

--50 neighborselect * fra UDFNearestNeighbors(38.90606200,-76.92943500,50)GO--200 neighborselect * fra UDFNearestNeighbors( 38.90606200,-76.929403500)GO03500,

  1. hvad er materialiserede synspunkter i oracle?

  2. Table Print passer ikke til sidestørrelsen

  3. Sådan ændres bruger til superbruger i PostgreSQL

  4. Afslut hængt forespørgsel (inaktiv i transaktion)