Jika semua yang ingin Anda lakukan dengan SqlGeography adalah melacak titik dan memanfaatkan indeks spasial SQL Server 2008, Anda dapat, seperti yang telah dicatat orang lain, menyembunyikan kolom data spasial Anda dari Linq ke SQL dan menggunakan UDF atau prosedur tersimpan. Misalkan Anda memiliki tabel AddressFields yang menyertakan bidang Latitude dan Longitude. Tambahkan tabel itu ke file DBML Anda, dan tulis kode apa pun yang Anda inginkan yang menyetel bidang Lintang dan Bujur. Kemudian, kode SQL di bawah ini akan menambahkan bidang Geo geogarphy ke tabel itu dan membuat pemicu di database yang secara otomatis menyetel bidang Geo berdasarkan bidang Latitude dan Longitude. Sementara itu, kode di bawah ini juga membuat UDF lain yang berguna dan prosedur tersimpan:DistanceBetween2 (Saya sudah memiliki DistanceBetween) mengembalikan jarak antara alamat yang diwakili dalam AddressField dan pasangan garis lintang/garis bujur yang ditentukan; DistanceWithin mengembalikan berbagai bidang dari semua AddressFields dalam jarak mil tertentu; UDFDistanceWithin melakukan hal yang sama seperti fungsi yang ditentukan pengguna (berguna jika Anda ingin menyematkan ini dalam kueri yang lebih besar); dan UDFNearestNeighbors mengembalikan bidang dari AddressField yang sesuai dengan jumlah tetangga yang ditentukan terdekat dengan titik tertentu. (Salah satu alasan untuk menggunakan UDFNearestNeighbors adalah bahwa SQL Server 2008 tidak akan mengoptimalkan penggunaan indeks spasialnya jika Anda hanya memanggil order dengan memanggil DistanceBetween2.)
Anda harus menyesuaikan ini dengan mengubah AddressFields ke tabel Anda dan menyesuaikan bidang dari tabel yang ingin Anda kembalikan (lihat kode di sekitar referensi ke AddressFieldID). Anda kemudian dapat menjalankan ini di database Anda dan menyalin prosedur tersimpan dan UDF yang dihasilkan ke DBML Anda, dan kemudian Anda dapat menggunakannya dalam kueri. Secara keseluruhan, ini memungkinkan Anda memanfaatkan indeks spasial poin dengan cukup mudah.
-------------------------------------------- --------------------------------------------------------
--[1]
--INITIAL AUDITselect * from dbo.AddressFieldsGO--ADD COLUMN GEOIF EXISTS (PILIH nama FROM sysindexes WHERE name ='SIndx_AddressFields_geo')DROP INDEX SIndx_AddressFields_geoSyGOIFscolums_geo ON AddressFields WHERE a.id =b.id dan a.name ='AddressFields' dan b.name ='Geo' dan a.type ='U' ) ALTER TABLE AddressFields DROP COLUMN Tabel GeoGOalter AddressFields menambahkan geografi Geo
--[2]
--SET GEO VALUEGOUPDATE AddressFieldsSET Geo =geografi::STPointFromText('POINT(' + CAST([Bujur] AS VARCHAR(20)) + ' ' + CAST([Lintang] AS VARCHAR(20)) + ')', 4326)
--[3] BUAT INDEKS
JIKA ADA (PILIH nama FROM sysindexes WHERE name ='SIndx_AddressFields_geo')DROP INDEX SIndx_AddressFields_geo ON AddressFieldsGOCREATE SPATIAL INDEX SIndx_AddressFields_geo-AlamatSUDATE)-alamat STUDATEON(AlamatKode STUD)> --[4] BUAT PROSEDUR USP_SET_GEO_VALUE PARA 1 LATITUDE 2 LONGITUDE
JIKA ADA (PILIH nama FROM sysobjects WHERE name ='USPSetGEOValue' AND type ='P') DROP PROC USPSetGEOValueGOGOCREATE PROC USPSetGEOValue @lintang desimal(18,8), @desimal bujur(18,8)SEBAGAI UPDATE AddressFields SET Geo =geografi::STPointFromText('POINT(' + CAST(@longitude AS VARCHAR(20)) + ' ' + CAST(@latitude AS VARCHAR(20)) + ')', 4326) WHERE [Bujur] contoh @sqldat.com dan [Lintang] =@latitudeGO--TESTEXEC USPSetGEOValue 38.87350500,-76.97627500GO
--[5] BUAT PEMICU PADA LAT/LONG VALUE CHANGE/INSERT ---> SET GEOCODE
JIKA ADA (PILIH nama FROM sysobjects WHERE name ='TRGSetGEOCode' AND type ='TR')DROP TRIGGER TRGSetGEOCodeGOCREATE TRIGGER TRGSetGEOCode ON AddressFieldsAFTER INSERT,UPDATEAS DECLARE @lintang desimal(18,(8) 18,8) JIKA ( UPDATE (Lintang) ATAU UPDATE (Bujur) ) MULAI PILIH @lintang =lintang ,@bujur =bujur dari sisipan UPDATE AddressFields SET Geo =geografi::STPointFromText('POINT(' + CAST(@longitude AS VARCHAR) (20)) + ' ' + CAST(@latitude AS VARCHAR(20)) + ')', 4326) WHERE [Bujur] [email protected] dan [Lintang] =@latitude AKHIR LAINNYA MULAI PILIH @latitude =latitude , @bujur =bujur dari dimasukkan UPDATE AddressFields SET Geo =geografi::STPointFromText('POINT(' + CAST(@longitude AS VARCHAR(20)) + ' ' + CAST(@latitude AS VARCHAR(20)) + ')', 4326) MANA [Longitu de] [email protected] dan [Latitude] =@latitude AKHIR PERGI
--[6] BUAT PROC USP_SET_GEO_VALUE_INITIAL_LOAD ----> HANYA SATU KALI BERJALAN
JIKA ADA (PILIH nama FROM sysobjects WHERE name ='USPSetAllGeo' AND type ='P') DROP PROC USPSetAllGeoGOCREATE PROC USPSetAllGeoASUPDATE AddressFieldsSET Geo =geografi::STPointFromText('POINT(' + CAST([Longitude] AS VARCHAR(20)) + ' ' + CAST([Lintang] AS VARCHAR(20)) + ')', 4326)GO
--[7] PROC DistanceBetween YANG ADA, yang mengembalikan jarak antara dua titik yang ditentukan
--menurut pasangan koordinat lintang/bujur. --ALTER PROC DistanceBetween2
JIKA ADA (PILIH nama FROM sysobjects WHERE name ='DistanceBetween2' AND type ='FN')DROP FUNCTION DistanceBetween2GOCREATE FUNCTION [dbo].[DistanceBetween2] (@AddressFieldID sebagai int, @Lat1 sebagai nyata,@Long1 sebagai nyata) RETURNS realASBEGIN MENYATAKAN @KMperNM float =1.0/1.852; DECLARE @nwi geografi =(pilih geo dari addressfields di mana AddressFieldID =@AddressFieldID) DECLARE @edi geografi =geografi::STPointFromText('POINT(' + CAST(@Long1 AS VARCHAR(20))) + ' ' + CAST(@Lat1 AS VARCHAR(20)) + ')', 4326) DECLARE @dDistance as real =(SELECT (@nwi.STDistance(@edi)/1000.0) * @KMperNM) return (@dDistance); SELESAI
PERGI--UJI
DistanceBetween2 12159,40.75889600,-73.99228900
--[8] BUAT PROSEDUR USPDistanceDalam
-- MENGEMBALIKAN DAFTAR ALAMAT DARI tabel AddressFields
JIKA ADA (PILIH nama FROM sysobjects WHERE name ='USPDistanceWithin' AND type ='P')DROP PROCEDURE USPDistanceWithin
GOCREATE PROCEDURE [dbo].USPDistanceWithin (@lat sebagai nyata,@sepanjang nyata, @jarak sebagai float)ASBEGIN MENYATAKAN @edi geografi =geografi::STPointFromText('POINT(' + CAST(@Long AS VARCHAR(20)) + ' ' + CAST(@Lat AS VARCHAR(20)) + ')', 4326) SET @distance =@distance * 1609.344 -- ubah jarak menjadi meter pilih AddressFieldID ,FieldID ,AddressString ,Latitude ,Longitude ,LastGeocode ,Status --,Geo dari AddressFields a WITH(INDEX(SIndx_AddressFields_geo)) di mana a.geo.STDistance(@edi) <=@Distance END
PERGI
--UJI
--dalam 3 milUSPDjarakDalam 38.90606200,-76.92943500,3GO--dalam 5 milUSPDJarakDalam 38.90606200,-76.92943500,5GO--dalam 10 milUSPDJarak Dalam 38.90606200,-76.92943500,10
--[9] BUAT FUNGSI FNDDistanceWithin
-- MENGEMBALIKAN DAFTAR ALAMAT DARI tabel AddressFields
JIKA ADA (PILIH nama FROM sysobjects WHERE name ='UDFDistanceWithin' AND type ='TF')DROP FUNCTION UDFDistanceWithin
GOCREATE FUNCTION UDFDistanceWithin (@lat sebagai nyata,@sepanjang nyata, @jarak sebagai nyata)RETURNS @AddressIdsToReturn TABLE ( AddressFieldID INT ,FieldID INT )ASBEGIN MENYATAKAN @edi geografi =geografi::STPointFromText('POINT( ' + CAST(@Long AS VARCHAR(20)) + ' ' + CAST(@Lat AS VARCHAR(20)) + ')', 4326) SET @distance =@distance * 1609.344 -- ubah jarak menjadi meter INSERT INTO @ AddressIdsToReturn pilih AddressFieldID ,FieldID dari AddressFields a WITH(INDEX(SIndx_AddressFields_geo)) di mana a.geo.STDistance(@edi) <=@Distance RETURN END
PERGI
--UJI
--dalam 3 mil pilih * dari UDFDistanceWithin(38.90606200,-76.92943500,3)GO--dalam 5 milpilih * dari UDFDistanceWithin( 38.90606200,-76.92943500,5)GO--dalam 10 milpilih * dari UDFDistanceWithin( 38.90606200,-76.92943500,10)
--[9] BUAT FUNGSI UDFNearestNeighbors
-- MENGEMBALIKAN DAFTAR ALAMAT DARI tabel AddressFields
JIKA ADA (PILIH nama FROM sysobjects WHERE name ='UDFNearestNeighbors' AND type ='TF') DROP FUNCTION UDFNearestNeighbors
PERGI
JIKA ADA (PILIH nama FROM sysobjects WHERE name ='numbers' AND xtype ='u')DROP TABLE number
GO-- Pertama, buat tabel Numbers yang akan kita gunakan di bawah ini.PILIH TOP 100000 IDENTITY(int,1,1) AS n INTO numbers FROM MASTER..spt_values a, MASTER..spt_values b BUAT UNIK CLUSTERED INDEX idx_1 PADA angka(n)FUNGSI GOCREATE UDFNearestNeighbors (@lat sebagai nyata,@sepanjang nyata, @neighbors sebagai int)RETURNS @AddressIdsToReturn TABLE ( AddressFieldID INT ,FieldID INT )ASMULAI MENYATAKAN geografi:@ediint =From geografi POINT(' + CAST(@Long AS VARCHAR(20)) + ' ' + CAST(@Lat AS VARCHAR(20)) + ')', 4326) DECLARE @start FLOAT =1000; DENGAN NearestPoints SEBAGAI ( SELECT TOP(@neighbors) WITH TIES *, AddressFields.geo.STDistance(@edi) AS dist FROM Numbers GABUNG AddressFields WITH(INDEX(SIndx_AddressFields_geo)) DI AddressFields.geo.STDistance(@edi) <@start POWER(2,Numbers.n) ORDER OLEH n ) INSERT INTO @AddressIdsToReturn SELECT TOP(@neighbors) AddressFieldID ,FieldID FROM NearestPoints ORDER OLEH n DESC, dist RETURN END
PERGI
--UJI
--50 neighborselect * dari UDFNearestNeighbors(38.90606200,-76.92943500,50)GO--200 neighborselect * dari UDFNearestNeighbors( 38.90606200,-76.92943500,200)GO