4

我在数据库中有一个表,其中包含一些带有纬度和经度的邮政编码,例如:

Id  PostCode    Latitude         Longitude
1   ll29 8ht    53.2973289489746    -3.72970223426819

该表由 MVC 代码优先应用程序生成,经纬度数据类型为实数

我有一个存储过程,将 searchLatitude 和 searchLongitude 作为输入,然后计算距离:

CREATE PROCEDURE [dbo].[StockistSearch] 
    @searchLat float = 0,
    @searchLng float = 0
AS
BEGIN
    SET NOCOUNT ON;
SELECT top 40 
s.Id as Id,
a.Company as Company,
a.FirstName as FirstName,
a.LastName as LastName,
a.Address1 as Address1,
a.Address2 as Address2,
a.City as City,
a.ZipPostalCode as ZipPostalCode,
a.PhoneNumber as PhoneNumber,
a.FaxNumber as FaxNumber,
a.Email as Email,
s.latitude as Latitude,
s.longitude as Longitude,
( 3959 * acos( cos( radians(@searchLat) )
* cos( radians( s.latitude ) )
* cos( radians( s.longitude )
- radians(@searchLng) )
+ sin( radians(@searchLat) )
* sin( radians( s.latitude ) ) ) )
AS Distance
FROM Stockist s, Customer c, Address a
where s.CustomerId = c.Id
and c.ShippingAddress_Id = a.Id     
ORDER BY distance
END

如果我通过 SQL Server Management Studio 执行此操作,它将执行以下操作:

DECLARE @return_value int

EXEC    @return_value = [dbo].[StockistSearch]
    @searchLat = 53.29,
    @searchLng = -3.72

SELECT  'Return Value' = @return_value

GO

正确返回距离(0.645英里)

但是,当使用以下应用程序执行时:

var result = this.Database.SqlQuery<TEntity>(commandText, parameters).ToList();

根据跟踪,它执行:

exec sp_executesql N'StockistSearch',N'@searchLat float,@searchLng float',@searchLat=53.29,@searchLng=-3.72

这导致计算距离的结果完全不同(并且错误),(它返回距离 3688.96 英里!)

我已经在调试中逐步完成了代码,并且正确输入了参数,并确认 exec sp_executesql 给出的结果与直接在 SQL Server 管理工作室中运行时的 EXEC 不同

我完全不知道为什么会发生这种情况,尽管存储过程似乎运行正常,但通过应用程序显示的结果完全错误。

在我发疯之前,请有人给我一些建议!!

谢谢

更新

感谢到目前为止的所有评论,感谢@McKay,我将其缩小到忽略从 exec sp_executesql 调用时的输入参数,并且纬度和经度都使用默认值 0。如果我删除默认值,我会收到错误消息:

Procedure or function 'StockistSearch' expects parameter '@searchLat', which was not supplied.

SQL查询是

exec sp_executesql N'StockistSearch', N'@searchLat real, @searchLng real',@searchLat=53.29,@searchLng=-3.72

此 sql 由实体框架自动生成(代码优先 MVC EF 目前不支持存储过程,但应该能够使用 DbContext 中的以下内容查询存储过程:)

var result = this.Database.SqlQuery<TEntity>(commandText, parameters).ToList();

将不胜感激任何进一步的帮助

固定的 :-)

调用时:

var result = this.Database.SqlQuery<TEntity>(commandText, parameters).ToList();

命令文本必须附加参数,因此

commandText = "StockistSearch @searchLat,@searchLng"

所以生成的sql是;

exec sp_executesql N'StockistSearch @searchLat,@searchLng', N'@searchLat real, @searchLng real',@searchLat=53.29,@searchLng=-3.72

它现在接受输入参数并计算正确的距离

4

4 回答 4

1

如此不同的数字让我觉得它可能正在使用默认值?你有没有去掉默认值?

也许您还可以将参数添加到选择中,以确保您得到您所期望的。

SELECT top 40 
    @searchLatitude,
    @searchLongitude,
    l.Id as Id,
    l.Postcode as Postcode,
    l.latitude as Latitude,
    l.longitude as Longitude,

这可能有助于您的调试过程。

于 2013-08-16T14:29:15.593 回答
0

你的过程中有错误。

( 3959 * acos( cos( radians(@searchLatitude) )
* cos( radians( l.latitude ) )
* cos( radians( l.longitude )
- radians(@searchLongitude) )
+ sin( radians(@searchLat) )
* sin( radians( l.latitude ) ) ) )

一个使用@searchLat,一个使用@searchLatitude

等等,proc 似乎选择了表,并且没有返回值,但是您的执行需要一个 out 参数?

于 2013-08-16T14:11:07.297 回答
0

不同之处在于它的调用方式。

您的 SSMS 调用会返回返回值。

您的sp_executesql调用将返回数据集。我猜第 40 个最近的零售商在 3688.96 英里之外

于 2013-08-16T14:54:47.387 回答
0

你有两个存储过程,一个叫做DistanceSearch,一个叫做StockistSearch?从您的代码中看起来是这样。您确定正在调用正确的程序吗?

于 2013-08-16T14:09:23.363 回答