0

我正在尝试用我的应用程序做一些聪明的事情。我有一个表格,广告 - 其中包含有关汽车的信息:型号、里程等。该表格通过外键与其他一些表格相关,例如,模型名称是通过链接到“VehicleModels”表格等的外键检索的。

在应用程序的“实体”目录(映射到数据库中表的类)中,我有一个用于 Adverts 表的 Advert.cs。这有几个属性,EF 被告知忽略(在流利的 api 中),因为它们没有映射到 Adverts 表中的实际字段。

这些字段背后的想法是将计算出的与用户输入的邮政编码(邮政编码)的距离存储在搜索表单中,如果他们只想查看特定半径内的可用汽车,则该搜索表单会过滤 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);
    }
}

我遇到的问题是,为了为这两个字段分配值,我必须使用 .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 ,但当然此时所有行都已被拉出。

我的问题是,我该如何重做这个?有没有更好的方法在我的 Advert 实体类中使用这些非映射属性?我正在我的家用 PC 上工作 - C2D @ 3.4GHz,2GB 内存 - 慢速查询可以在属性网络主机上运行吗?

4

1 回答 1

0

您不能在客户端功能上使用服务器端分页。这是简短的答案。假设我正确理解您的需求(根据与给定邮政编码的接近程度过滤列表),我过去使用的解决方案是将每个“广告”记录存储为该记录的邮政编码的纬度/经度。该数据被持久化。

然后,当需要查询时,根据与中心的 X 距离(用户提供的邮政编码)计算边界框(lat1,lng1,lat2,lng2),并根据 lat/lng 符合此范围的记录过滤查询结果盒子。然后,您可以应用客户端计算来进一步和更准确地过滤列表,但是使用此方法,您可以建立一个基本过滤器以最大限度地减少提取的记录数。

编辑:您可以根据abs(latU-latR)和abs(lngU-lngR)的绝对距离对查询结果进行排序,其中latU/lngU是用户提供的邮政编码的lat/lng latR/lngR 是数据库中记录的 lat/lng。

于 2012-04-12T04:23:48.127 回答