我们最近有一个项目,我们不得不在谷歌地图上绘制机构,但是使用地址来确定机构是否已经采取长期加载的方式。因此,我们决定将lat / lng存储在数据库中以对照机构记录。为此,我们创建了一个存储过程usp_web_kam_Geocode
,调用GoogleMaps地理编码服务以返回随后存储的坐标。
我们在trg_Geocode
之后tblInstitution
创建了一个触发器INSERT, UPDATE
,它提供了一些条件(bIncludeInKAMMap = 1
,即要绘制它),然后调用usp_web_kam_Geocode
并更新记录上的坐标。
将此触发器添加到表格后,当从网络应用程序调用时,对usp_web_InsertUpdateInstitution
(负责插入和更新tblInstitution
)的任何调用都会失败而不会出现错误。
我们已使用SQL Server Profiler跟踪此usp_web_InsertUpdateInstitution
的调用,该调用产生以下内容:
declare @p1 int
set @p1=149078313
exec usp_web_InsertUpdateInstitution @lInstitutionID=@p1 output,@lRegionID=132,@TOREFMadisunNumber=N'',@sSageNumber=N'',@sName=N'Replication Test Changed',@Xaddress=N'',@sPostCode=N'GU97DR',@sPhone=N'',@sFax=N'',@lInstitutionTypeID=14,@sNote=N'',@lModifiedByID=0,@sAddress1=N'',@sAddress2=N'',@sAddress3=N'',@sTown=N'',@sCounty=N'',@TOREFCountry=N'',@sWebsite=N'',@lDistributorID=2,@XFCRef=0,@sSICCode=N'',@lEmployees=0,@sSource=N'',@bKeyAccount=0,@TOREFProspectType=N'',@sVAddress1=N'',@sVAddress2=N'',@sVAddress3=N'',@sVTown=N'',@sVCounty=N'',@TOREFVCountry=N'',@sVPostcode=N'',@bHasSepticUnit=0,@lBusinessManagerTempID=0,@lProspectTypeID=1,@lGroupID=1,@lCountryID=180,@lVCountryID=-2,@bDeleted=0,@lValueID=NULL,@sGeneralEmail=N'',@lMarketingID=48509669,@sVisitingAddress=N'',@bIsolator=0,@bLAF=0,@bGradeAB=0,@bGradeCD=0,@bUnclassified=0,@bNoProduction=0,@sIsolatorQty=N'',@sLAFQty=N'',@sGradeABArea=N'',@sGradeCDArea=N'',@sUnclassifiedArea=N'',@bIncludeInKAM=1,@fLat=55.378050999999999,@fLong=-3.4359730000000002,@bRespQuality=0,@bRespMicro=0,@bRespPurchasing=0,@bRespValidation=0,@bKindIsolator=0,@bKindRABS=0,@bKindOLA=0,@bKindOLB=0,@bKindOLC=0,@bKindOLD=0,@lNoCleanroomOperatives=0,@sProductsManufactured=N'',@sComments=N'Test wm4',@lValueAlcohol=0,@lValueBiocides=0,@lValueWipes=0,@lValueEquipment=0,@lValueNonSterile=0,@lValueOther=0,@lGeocodeAttempts=6,@sGeocodeLastStatus=N'OK'
select @p1
屏幕截图的前两行来自网络应用程序(不起作用),最后两行来自SSMS(工作正常)
但是如果我们从上面复制确切的SQL并在SSMS中运行它(使用与Web应用程序相同的登录名),它可以正常插入或更新记录并成功从中检索lat / lng网络服务
Public Function Save() As Integer
Dim cn As New SqlConnection(My.Settings.ShieldCRMConnectionString)
Dim cmd As New SqlCommand
Dim strSQL As String = "usp_web_InsertUpdateInstitution"
Try
cn.Open()
cmd.Connection = cn
cmd.CommandText = strSQL
cmd.CommandType = CommandType.StoredProcedure
Dim prmInstitutionID As New SqlParameter
prmInstitutionID.ParameterName = "@lInstitutionID"
prmInstitutionID.Value = intInstitutionID
prmInstitutionID.Direction = ParameterDirection.InputOutput
cmd.Parameters.Add(prmInstitutionID)
'** Parameters clipped out for readability
cmd.ExecuteNonQuery()
Return cmd.Parameters("@lInstitutionID").Value
Catch ex As Exception
Elmah.ErrorSignal.FromCurrentContext.Raise(ex)
Return -1
Finally
cmd.Dispose()
cn.Close()
cn.Dispose()
End Try
ALTER TRIGGER [dbo].[trg_Geolocation] ON [dbo].[tblInstitution] AFTER INSERT, UPDATE
AS
BEGIN
DECLARE @lInstitutionID INT
DECLARE @sAddress1 VARCHAR(500)
DECLARE @sAddress2 VARCHAR(500)
DECLARE @sAddress3 VARCHAR(500)
DECLARE @sTown VARCHAR(500)
DECLARE @sCounty VARCHAR(500)
DECLARE @sPostcode VARCHAR(500)
DECLARE @sCountry VARCHAR(500)
DECLARE @lCountryID INT
DECLARE cur CURSOR FOR
SELECT lInstitutionID,
sAddress1,
sAddress2,
sAddress3,
sTown,
sCounty,
sPostCode,
C.lCountryID,
C.sName AS sCountry
FROM inserted I
INNER JOIN refCountry C ON I.lCountryID = C.lCountryID
WHERE ISNULL(bIncludeInKAM, 0) = 1
OPEN cur
FETCH NEXT FROM cur INTO @lInstitutionID, @sAddress1, @sAddress2, @sAddress3, @sTown, @sCounty, @sPostCode, @lCountryID, @sCountry
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @fLat FLOAT
DECLARE @fLng FLOAT
DECLARE @sAddress VARCHAR(MAX)
DECLARE @sLastStatus VARCHAR(200)
SELECT @fLat = NULL, @fLng = NULL, @sAddress = NULL
SELECT @sAddress =
CASE WHEN REPLACE(REPLACE(ISNULL(@sAddress1 + ', ', '') + ISNULL(@sAddress2 + ', ', '') + ISNULL(@sAddress3 + ', ', '') + ISNULL(@sTown + ', ', '') + ISNULL(@sCounty + ', ', '') + @sCountry, ', , , ', ', '), ', , ', ', ')
LIKE ', %' THEN RIGHT(REPLACE(REPLACE(ISNULL(@sAddress1 + ', ', '') + ISNULL(@sAddress2 + ', ', '') + ISNULL(@sAddress3 + ', ', '') + ISNULL(@sTown + ', ', '') + ISNULL(@sCounty + ', ', '') + @sCountry, ', , , ', ', '), ', , ', ', '),
LEN(REPLACE(REPLACE(ISNULL(@sAddress1 + ', ', '') + ISNULL(@sAddress2 + ', ', '') + ISNULL(@sAddress3 + ', ', '') + ISNULL(@sTown + ', ', '') + ISNULL(@sCounty + ', ', '') + @sCountry, ', , , ', ', '), ', , ', ', ')) - 2)
ELSE REPLACE(REPLACE(ISNULL(@sAddress1 + ', ', '') + ISNULL(@sAddress2 + ', ', '') + ISNULL(@sAddress3 + ', ', '') + ISNULL(@sTown + ', ', '') + ISNULL(@sCounty + ', ', '') + @sCountry, ', , , ', ', '), ', , ', ', ') END
BEGIN TRY
EXEC usp_web_kam_Geocode @sAddress = @sAddress OUTPUT, @fLat = @fLat OUTPUT, @fLng = @fLng OUTPUT, @sGeocodeLastStatus = @sLastStatus OUTPUT
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE()
END CATCH
IF NOT (@fLat IS NULL AND @fLng IS NULL)
BEGIN
UPDATE tblInstitution
SET fLat = @fLat,
fLong = @fLng,
lGeocodeAttempts = ISNULL(lGeocodeAttempts, 0) + 1,
sGeocodeLastStatus = @sLastStatus
WHERE lInstitutionID = @lInstitutionID
END
FETCH NEXT FROM cur INTO @lInstitutionID, @sAddress1, @sAddress2, @sAddress3, @sTown, @sCounty, @sPostCode, @lCountryID, @sCountry
END
CLOSE cur
DEALLOCATE cur
END
ALTER PROCEDURE [dbo].[usp_web_kam_Geocode]
@sAddress VARCHAR(80) = NULL OUTPUT,
@sCity VARCHAR(40) = NULL OUTPUT,
@sState VARCHAR(40) = NULL OUTPUT,
@sCounty VARCHAR(40) = NULL OUTPUT,
@sCountry VARCHAR(40) = NULL OUTPUT,
@sPostCode VARCHAR(20) = NULL OUTPUT,
@sGeocodeLastStatus VARCHAR(200) = NULL OUTPUT,
@fLat FLOAT = NULL OUTPUT,
@fLng FLOAT = NULL OUTPUT,
@sMapURL VARCHAR(1024) = NULL OUTPUT
AS
BEGIN
SET NOCOUNT ON
DECLARE @sURL varchar(MAX)
SET @sURL = 'http://maps.google.com/maps/api/geocode/xml?sensor=false&address=' +
CASE WHEN @sAddress IS NOT NULL THEN @sAddress ELSE '' END +
CASE WHEN @sCity IS NOT NULL THEN ', ' + @sCity ELSE '' END +
CASE WHEN @sState IS NOT NULL THEN ', ' + @sState ELSE '' END +
CASE WHEN @sPostCode IS NOT NULL THEN ', ' + @sPostCode ELSE '' END +
CASE WHEN @sCountry IS NOT NULL THEN ', ' + @sCountry ELSE '' END
SET @sURL = REPLACE(@sURL, ' ', '+')
DECLARE @Response varchar(8000)
DECLARE @XML xml
DECLARE @Obj int
DECLARE @Result int
DECLARE @HTTPStatus int
DECLARE @ErrorMsg varchar(MAX)
EXEC @Result = sp_OACreate 'MSXML2.ServerXMLHttp', @Obj OUT
BEGIN TRY
EXEC @Result = sp_OAMethod @Obj, 'open', NULL, 'GET', @sURL, false
EXEC @Result = sp_OAMethod @Obj, 'setRequestHeader', NULL, 'Content-Type', 'application/x-www-form-urlencoded'
EXEC @Result = sp_OAMethod @Obj, send, NULL, ''
EXEC @Result = sp_OAGetProperty @Obj, 'status', @HTTPStatus OUT
EXEC @Result = sp_OAGetProperty @Obj, 'responseXML.xml', @Response OUT
END TRY
BEGIN CATCH
SET @ErrorMsg = ERROR_MESSAGE()
END CATCH
EXEC @Result = sp_OADestroy @Obj
IF (@ErrorMsg IS NOT NULL) OR (@HTTPStatus <> 200) BEGIN
SET @ErrorMsg = 'Error in Geocode: ' + ISNULL(@ErrorMsg, 'HTTP result is: ' + CAST(@HTTPStatus AS varchar(10)))
RAISERROR(@ErrorMsg, 16, 1, @HTTPStatus)
RETURN
END
SET @XML = CAST(@Response AS XML)
SET @sGeocodeLastStatus = @XML.value('(/GeocodeResponse/status) [1]', 'varchar(200)')
SET @fLat = @XML.value('(/GeocodeResponse/result/geometry/location/lat) [1]', 'numeric(9,6)')
SET @fLng = @XML.value('(/GeocodeResponse/result/geometry/location/lng) [1]', 'numeric(9,6)')
SET @sCity = @XML.value('(/GeocodeResponse/result/address_component[type="locality"]/long_name) [1]', 'varchar(40)')
SET @sState = @XML.value('(/GeocodeResponse/result/address_component[type="administrative_area_level_1"]/short_name) [1]', 'varchar(40)')
SET @sPostCode = @XML.value('(/GeocodeResponse/result/address_component[type="postal_code"]/long_name) [1]', 'varchar(20)')
SET @sCountry = @XML.value('(/GeocodeResponse/result/address_component[type="country"]/short_name) [1]', 'varchar(40)')
SET @sCounty = @XML.value('(/GeocodeResponse/result/address_component[type="administrative_area_level_2"]/short_name) [1]', 'varchar(40)')
SET @sAddress =
ISNULL(@XML.value('(/GeocodeResponse/result/address_component[type="street_number"]/long_name) [1]', 'varchar(40)'), '???') + ' ' +
ISNULL(@XML.value('(/GeocodeResponse/result/address_component[type="route"]/long_name) [1]', 'varchar(40)'), '???')
SET @sMapURL = 'http://maps.google.com/maps?f=q&hl=en&q=' + CAST(@fLat AS varchar(20)) + '+' + CAST(@fLng AS varchar(20))
END