2011-06-20 12 views
1

Nerddinnerと同じ関数 "distancebetween"を実装しました。私は空港のリポジトリを作成し、これらのメソッドを持っている:Entity Frameworkのデータベース関数が結果を返せませんでした

public IQueryable<AllAirports> ReturnAllAirportWithIn50milesOfAPoint(double lat, double lon) 
    { 
     var airports = from d in im.AllAirports 
       where DistanceBetween(lat, lon, (double)d.Lat, (double)d.Lon) < 1000.00 
       select d; 
     return airports; 
    } 

    [EdmFunction("AirTravelModel.Store", "DistanceBetween")] 
    public static double DistanceBetween(double lat1, double long1, double lat2, double long2) 
    { 
     throw new NotImplementedException("Only call through LINQ expression"); 
    } 

私はそれをテストしたとき、それは示しています

ベース{ "指定したメソッド『ダブル間の距離(ダブル、ダブル、ダブル、ダブル』)過負荷は、渡された引数と一致しないため、タイプ「AirTravelMVC3.Models.Repository.AirportRepository」上のエンティティにLINQに ストア発現を翻訳することはできません。 "} System.SystemException {System.NotSupportedException}

これはなぜ起こるかについてのアイデアはありますか?私の仕事と奇妙な違いは、エンティティフレームワークでPOCOプラグインを使用したことだけです。

次のようにSQL UDFは、それがデータベースに非常にうまく機能し、次のとおりです。

 
CREATE FUNCTION [dbo].[DistanceBetween](@Lat1 as real, 
@Long1 as real, @Lat2 as real, @Long2 as real) 
RETURNS real 
AS 
BEGIN 

DECLARE @dLat1InRad as float(53); 
SET @dLat1InRad = @Lat1 * (PI()/180.0); 
DECLARE @dLong1InRad as float(53); 
SET @dLong1InRad = @Long1 * (PI()/180.0); 
DECLARE @dLat2InRad as float(53); 
SET @dLat2InRad = @Lat2 * (PI()/180.0); 
DECLARE @dLong2InRad as float(53); 
SET @dLong2InRad = @Long2 * (PI()/180.0); 

DECLARE @dLongitude as float(53); 
SET @dLongitude = @dLong2InRad - @dLong1InRad; 
DECLARE @dLatitude as float(53); 
SET @dLatitude = @dLat2InRad - @dLat1InRad; 
/* Intermediate result a. */ 
DECLARE @a as float(53); 
SET @a = SQUARE (SIN (@dLatitude/2.0)) + COS (@dLat1InRad) 
* COS (@dLat2InRad) 
* SQUARE(SIN (@dLongitude/2.0)); 
/* Intermediate result c (great circle distance in Radians). */ 
DECLARE @c as real; 
SET @c = 2.0 * ATN2 (SQRT (@a), SQRT (1.0 - @a)); 
DECLARE @kEarthRadius as real; 
/* SET kEarthRadius = 3956.0 miles */ 
SET @kEarthRadius = 6376.5;  /* kms */ 

DECLARE @dDistance as real; 
SET @dDistance = @kEarthRadius * @c; 
return (@dDistance); 
END 
+0

「DistanceBetween()」と呼ばれるSQL Server UDFがありますか?投稿できますか? –

+0

@ p.campbell私は自分の投稿を編集し、UDFを含めました。 – Seen

答えて

1

私はDinnerRepositoryクラスにこれを追加する必要がありました、既存のNerdDinnerのソースを使用して、この使用POCOSを行うために:私は、DBスキーマにいくつかの変更を行い、「更新された後、私はこれと同じ例外が発生しました

public IQueryable<Dinner> FindByLocation(float latitude, float longitude) 
{ 
    List<Dinner> resultList = new List<Dinner>(); 

    var results = db.Database.SqlQuery<Dinner>("SELECT * FROM Dinners WHERE EventDate >= {0} AND dbo.DistanceBetween({1}, {2}, Latitude, Longitude) < 1000", DateTime.Now, latitude, longitude); 
    foreach (Dinner result in results) 
    { 
     resultList.Add(db.Dinners.Where(d => d.DinnerID == result.DinnerID).FirstOrDefault()); 
    } 

    return resultList.AsQueryable<Dinner>(); 
} 
+0

SQLクエリを関数を使用するのではなく直接実行します。 – Seen

+0

基本的にPOCOにEDMマッピングがないので、SQL Server上でこの関数を直接呼び出すことによってこの機能を利用する方法を思いつきました。 –

+0

次のバージョンで修正することを願っています – Seen

0

間の距離は問題が(@のp.campbellによりを示唆したとして)クエリジェネレータはdoesnのことですC#で実装されていると仮定すると、 「Tがそのまま動作するようにあなたのコードを取得するには間の距離

を計算する方法を知って、あなたは)

public IQueryable<AllAirports> ReturnAllAirportWithIn50milesOfAPoint(double lat, double lon) 
{ 
    var airports = from d in im.AllAirports.ToList() 
      where DistanceBetween(lat, lon, (double)d.Lat, (double)d.Lon) < 1000.00 
      select d; 
    return airports; 
} 

ToListメソッド(のような何かをする必要があるかもしれませんAllAirportを強制しますあなたのC#関数を使って、メモリ内で評価することができます。明らかに、これは膨大な数の空港に拡張されません。それが問題であれば、少数の空港を返す安価なインチ内の式を実行し、ToListした後、結果を絞り込むために距離を呼ぶという、大まかな「ボックス」クエリを実行することができます。

+0

ああ - 私はこれを書いているので、C#関数ではないSQL UDFであなたの投稿を更新するので、無視してください:-)しかし、単純なクエリに移動してDistanceBetweenをC#に移動すると、これは動作します! – Andiih

+0

私は試して、DistanceBetween関数で例外を返します。エンティティのフレームワークがSQL UDFと一致しないように見える – Seen

+0

POCOテンプレートとデータベース関数の間にいくつかのバグがあるかもしれないと思う...私は行くべき唯一の方法はC言語でこれらのコードを書き直すことだと思う# – Seen

0

データベースからのモデル "。

私のEDMX XMLとNerd Dinnerのオリジナルを比較したところ、私はDistanceBetween関数のすべてのタイプをNerd Dinnerが "float"とした "real"に変更したことがわかりました。フロートに戻して問題を解決しました。

関連する問題