たとえば、緯度と経度を含むいくつかの郵便番号で構成されるデータベースにテーブルがあります。
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 サーバー管理スタジオで実行すると、次のように実行されます。
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 マイルが返されます!)。
デバッグでコードをステップ実行し、パラメーターが正しく入力されていることを確認しました。実行 sp_executesql が、SQL サーバー管理スタジオで直接実行された場合の 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
入力パラメータを受け入れ、正しい距離を計算するようになりました