アプリで少し賢いことをしようとしています。車に関する情報を含む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 ホストで正常に実行されますか?