2012-04-12 6 views
0

私のアプリでちょっとしたことをしようとしています。私はテーブル、Advertsを持っています - 車に関する情報が含まれています:モデル、走行距離など。テーブルは外部キーを介して他のいくつかのテーブルに関連しています。モデル名は「VehicleModels」テーブルなどにリンクする外部キーを介して取得されます。大きいテーブルの.Skip()および.Take()の前に、エンティティフレームワーク4.1の.ToList()を呼び出す必要があります。

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

これらのフィールドの背後にあるアイデアは、ユーザが入力した郵便番号(郵便番号)から計算された距離を、特定の半径内で利用可能な車を見たい場合に広告テーブルをフィルタリングする検索フォームに格納することです。例えば:

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); 
    } 
} 

私がいる問題は、これらの二つのフィールドに値を割り当てるために、私が抱えているということですテーブルからすべての行を引っ張っている.ToList()を使用してください。数行しかない場合は正常に動作しますが、約1,000の場合は約です。 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ウェブサイトの検索フォームをご覧ください。

モデルがビューに渡される直前にすべてのフィルタが適用されると、.Skipと.Takeが適用されますが、今度はすべての行がプルされています。

私の質問は、これをやり直すにはどうすればいいですか?広告エンティティクラスでこれらのマップされていないプロパティを使用するより良い方法はありますか?私は自宅のPCで動作しています - C2D @ 3.4GHz、2GB RAM - 低速のクエリは不動産のウェブホストでOKですか?

答えて

0

クライアント側の機能でサーバー側のページングを使用することはできません。それは短い答えです。特定の郵便番号への近接性に基づいてリストをフィルタリングするために私があなたの必要性を正しく理解していると仮定すると、過去に使用した解決策は、そのレコードの郵便番号の緯度/経度をそれぞれの '広告'レコードに格納することです。このデータは保持されます。

次に、クエリの時間が来たら、中心からのX距離(ユーザー提供の郵便番号)に基づいて境界ボックス(lat1、lng1、lat2、lng2)を計算し、このボックス内に収まります。次に、クライアント側の計算を適用してリストをさらに正確にフィルタリングできますが、この方法を使用すると、プルされるレコードの数を最小限に抑えるベースフィルタを確立できます。

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