我的网站中有一个名为HotelDetail
的重页,在此页面中会加载与酒店相关的一些内容。酒店,酒店的服务,酒店的目的地,用户的评论,酒店的房间及其服务,价格和容量。
所有这些都将使用以下代码一次加载,现在我想优化此代码,优化此代码的解决方案是为了获得更好的性能和更高的可读性?有没有办法不加载所有的一次?
public PlaceViewModel GetPlaceDetail(string languageKey,string catKey , string placeKey, SearchViewModel searchOptions)
{
DateTime startDate = searchOptions.CheckIn.ToMiladiDateTime();
DateTime endDate = searchOptions.CheckOut.ToMiladiDateTime();
int nights = (int)endDate.Subtract(startDate).TotalDays;
placeViewModel.NightCount = nights;
var query = (from r in _unitOfWork.RoomServiceRepository.Get()
join
a in _unitOfWork.InventoryRepository.Get()
on r equals a.RoomService
where r.Room.Place.Id == place.Id && !r.SoftDelete && !r.Room.SoftDelete &&
a.Date >= startDate && a.Date < endDate && (a.CertainAvailability + a.FloatAvailability) > 0
select new { a, MaxCapacity = r.Room.Capacity + r.ExtraCapacity, r.RoomId });
placeViewModel.HasAvailability = query.ToList().Count != 0;
var grp = query.GroupBy(y => y.a.RoomServiceId)
.Select(z => new {
key = z.Key,
count = z.Count(),
minAvail = z.Min(ax => ax.a.CertainAvailability + ax.a.FloatAvailability),
minDate = z.Min(y => y.a.Date),
minPrice = z.Min(ax=>ax.a.Price),
price = z.Average(ax=>ax.a.Price) });
var tmp = query.Where(x => grp.Any(q =>
q.key == x.a.RoomServiceId &&
q.count == nights &&
q.minDate == x.a.Date)).ToList();
foreach (var item in tmp)
{
var roomViewModel = placeViewModel.Rooms.FirstOrDefault(x => x.Id == item.RoomId);
var avail = new AvailabilityViewModel(item.a, item.MaxCapacity);
avail.Availability = grp.FirstOrDefault(x => x.key == item.a.RoomServiceId).minAvail;
var otherInfos = grp.SingleOrDefault(x => x.key == item.a.RoomServiceId);
avail.JabamaPrice = otherInfos.price;
avail.JabamaMinPriceInPeriod = otherInfos.minPrice;
roomViewModel.Availabilites.Add(avail);
if (maxDiscount == null || (maxDiscount != null &&(maxDiscount.BoardPrice - maxDiscount.JabamaPrice) < (avail.BoardPrice - avail.JabamaPrice)))
maxDiscount = avail;
if (minPrice == null || (minPrice != null && avail.JabamaPrice > 0 && minPrice.JabamaPrice > avail.JabamaPrice))
minPrice = avail;
}
var discountQuery = tmp.Where(x => x.a.RoomService.ExtraCapacity == 0 && x.a.Date == minPrice.Date);
try
{
if (discountQuery.Any())
maxDiscountOfMinPercentageDay = tmp != null && minPrice != null ? discountQuery.Max(x => (x.a.BoardPrice - x.a.Price) / x.a.BoardPrice * 100) : 0;
else
maxDiscountOfMinPercentageDay = 0;
}
catch (Exception)
{
maxDiscountOfMinPercentageDay = 0;
}
foreach (var roomVM in placeViewModel.Rooms)
{
if (roomVM.Availabilites.Count() == 0)
roomVM.Availabilites.Add(new AvailabilityViewModel(-1));
}
}
答案 0 :(得分:0)
我远不熟悉Linq,但我确实知道SQL的一些陷阱。我注意到的一件事是你(和许多其他人!)使用.Count != 0
来确定是否有匹配的记录。在SQL中,这是一种非常低效的方法,因为系统将有效地遍历整个表以查找和计算与先决条件匹配的记录。在这种情况下,我建议使用WHERE EXISTS()
构造;我相信Linq有一些与.Any()
类似的东西。
这也是你在现实生活中所做的事情:当有人问你冰箱里是否还有奶酪时,你不会开始计算你在那里找到的所有类型的奶酪,而是在第一种奶酪之后停下来你看到并回答'是的,有&#39 ;;通过整个冰箱没有附加价值,只需要额外的时间。
PS:roomVM.Availabilites.Count() == 0
可能也是如此,使用反转逻辑可以更好地处理 ...
免责声明:可能是EntityFwk足够聪明,可以在后台为您优化这一点......我不知道;我非常怀疑它,但就像我说的那样,我不是专家。我建议首先弄清楚当前代码的每个部分需要多长时间,然后再优化最慢的代码。拥有基线还可以让您更好地了解您的更改是否有任何影响,无论是正面还是负面。