与 EXEC 相比,使用 exec sp_executesql 执行存储过程的结果不同

sam*_*eld 5 sql sql-server stored-procedures entity-framework

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

Id  PostCode    Latitude         Longitude
1   ll29 8ht    53.2973289489746    -3.72970223426819
Run Code Online (Sandbox Code Playgroud)

该表由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
Run Code Online (Sandbox Code Playgroud)

如果我通过 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
Run Code Online (Sandbox Code Playgroud)

正确返回距离(0.645 英里)

但是,当通过应用程序执行时,使用:

var result = this.Database.SqlQuery<TEntity>(commandText, parameters).ToList();
Run Code Online (Sandbox Code Playgroud)

根据跟踪,执行:

exec sp_executesql N'StockistSearch',N'@searchLat float,@searchLng float',@searchLat=53.29,@searchLng=-3.72
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

谢谢

更新

感谢迄今为止的所有评论,并感谢@McKay,我已将范围缩小到忽略从 exec sp_executesql 调用时的输入参数,并使用默认值 0 表示纬度和经度。如果我删除默认值,我会收到错误:

Procedure or function 'StockistSearch' expects parameter '@searchLat', which was not supplied.
Run Code Online (Sandbox Code Playgroud)

SQL 查询是

exec sp_executesql N'StockistSearch', N'@searchLat real, @searchLng real',@searchLat=53.29,@searchLng=-3.72
Run Code Online (Sandbox Code Playgroud)

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

var result = this.Database.SqlQuery<TEntity>(commandText, parameters).ToList();
Run Code Online (Sandbox Code Playgroud)

非常感谢任何进一步的帮助

固定的 :-)

打电话时:

var result = this.Database.SqlQuery<TEntity>(commandText, parameters).ToList();
Run Code Online (Sandbox Code Playgroud)

命令文本必须附加参数,以便

commandText = "StockistSearch @searchLat,@searchLng"
Run Code Online (Sandbox Code Playgroud)

所以生成的sql是;

exec sp_executesql N'StockistSearch @searchLat,@searchLng', N'@searchLat real, @searchLng real',@searchLat=53.29,@searchLng=-3.72
Run Code Online (Sandbox Code Playgroud)

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

McK*_*Kay 1

如此不同的数字让我觉得也许它正在使用某些东西的默认值?你把默认值去掉了吗?

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

SELECT top 40 
    @searchLatitude,
    @searchLongitude,
    l.Id as Id,
    l.Postcode as Postcode,
    l.latitude as Latitude,
    l.longitude as Longitude,
Run Code Online (Sandbox Code Playgroud)

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