0

アプリで少し賢いことをしようとしています。車に関する情報を含むAdvertsテーブルがあります:モデル、走行距離など。このテーブルは、外部キーを介して他のいくつかのテーブルに関連付けられています。たとえば、モデル名は、「VehicleModels」テーブルなどにリンクする外部キーを介して取得されます。

アプリの「エンティティ」ディレクトリ (データベース内のテーブルにマップするクラス) 内に、Adverts テーブル用の 1 つ、Advert.cs があります。これには、Adverts テーブルの実際のフィールドにマップされないため、EF が (流暢な API で) 無視するように指示されたプロパティがいくつかあります。

これらのフィールドの背後にある考え方は、ユーザーが検索フォームに入力した郵便番号 (郵便番号) から計算された距離を格納し、特定の半径内で利用可能な車のみを表示したい場合に、Adverts テーブルをフィルター処理することです。例えば:

IQueryable<Advert> FilteredAdverts = repository.Adverts
.Where(am => mfr == "" || am.Manufacturer == mfr) &&
    (am => model == etc etc...)

後で、距離を計算するために、コードは次のようになります。

if (userPostcode != null) {
    foreach (var ap in FilteredAdverts.ToList()) {
        distmiles = //calculate distance in miles
        distkm = //calculate distance in km

        ap.DistanceMiles = Convert.ToInt32(distmiles);
        ap.DistanceKm = Convert.ToInt32(distkm);
    }
}

私が抱えている問題は、これら 2 つのフィールドに値を割り当てるために、テーブルからすべての行を取得する .ToList() を使用する必要があることです。数行しかない場合は問題なく動作しますが、〜1,000の場合は約1時間かかります。2.2 秒、約 12,000 行に増やしたとき、フィルターが適用されていない場合、つまりすべてのアクティブな広告が返された場合、ページの読み込みに 32 秒かかりました。

.Skip と .Take を呼び出して表示する前にすべての広告をプルする理由は、検索フォームで使用できるフィルターが、単にリストを選択するのではなく、アクティブな現在のすべての広告の可能なオプション、つまり残り時間に基づいているためです。製造業者テーブルからの製造業者のリスト (ユーザーは、検索結果がない製造業者を選択できます)。例えば

VehicleManufacturers = (from vm in FilteredAdverts.Select(x => x.VehicleManufacturer).Distinct().OrderBy(x => x)
    select new SearchOptionsModel
    {
            Value = vm,
            Text = vm,
            Count = FilteredAdvertsVM.Where(x => x.VehicleManufacturer == vm).Count(),
    })

    .... filters for model, mileage etc

私が何を達成しようとしているのかを理解するには、Autotrader Web サイトの検索フォームを見てください。

すべてのフィルターが適用されると、モデルがビューに渡される直前に .Skip と .Take が適用されますが、もちろんこの時点までにすべての行がプルされています。

私の質問は、これをやり直すにはどうすればよいですか?Advert エンティティ クラスでこれらのマップされていないプロパティを利用するためのより良い方法はありますか? 私は自宅の PC (C2D @ 3.4GHz、2GB の RAM) で作業しています。低速のクエリは、適切な Web ホストで正常に実行されますか?

4

1 に答える 1

0

クライアント側の関数でサーバー側のページングを使用することはできません。それが短い答えです。あなたの必要性を正しく理解していると仮定すると(特定の郵便番号への近さに基づいてリストをフィルタリングするため)、過去に使用したソリューションは、各「広告」レコードをそのレコードの郵便番号の緯度/経度で保存することです。このデータは永続化されます。

次に、クエリを実行するときが来たら、中心からの X 距離 (ユーザーが指定した郵便番号) に基づいて境界ボックス (lat1、lng1、lat2、lng2) を計算し、lat/lng がこの範囲内に収まるレコードに基づいてクエリ結果をフィルタリングします。箱。その後、クライアント側の計算を適用してリストをさらに正確にフィルター処理できますが、この方法を使用すると、基本フィルターを確立して、取得されるレコードの数を最小限に抑えることができます。

編集: abs(latU-latR) および abs(lngU-lngR) の観点から、中心点からの絶対距離に基づいてクエリの結果を並べ替えることができます。ここで、latU/lngU はユーザーが指定した郵便番号の緯度/経度です。 latR/lngR は、データベース内のレコードの緯度/経度です。

于 2012-04-12T04:23:48.127 に答える