我如何使用NHibernate QueryOver重新创build这个复杂的SQL查询?

想象下面的(简化的)数据库布局: 数据库布局

我们有很多“假日”logging,涉及到某个特定date的特定住宿等。

我想从数据库中获得每个住宿(即最低价格)的“最佳”假期,给定一组search标准(例如持续时间,离开机场等)。

将有多个相同价格的logging,所以我们需要select保存(降序),然后按出发date升序。

我可以写SQL来做这个看起来像这样(我不是说这是最好的方式):

SELECT * FROM Holiday h1 INNER JOIN ( SELECT h2.HolidayID, h2.AccommodationID, ROW_NUMBER() OVER ( PARTITION BY h2.AccommodationID ORDER BY OfferSaving DESC ) AS RowNum FROM Holiday h2 INNER JOIN ( SELECT AccommodationID, MIN(price) as MinPrice FROM Holiday WHERE TradeNameID = 58001 /*** Other Criteria Here ***/ GROUP BY AccommodationID ) mp ON mp.AccommodationID = h2.AccommodationID AND mp.MinPrice = h2.price WHERE TradeNameID = 58001 /*** Other Criteria Here ***/ ) x on h1.HolidayID = x.HolidayID and x.RowNum = 1 

正如你所看到的,这使用另一个子查询中的子查询。

不过,由于几个原因,我的首选是在NHibernate中实现相同的结果。

理想情况下,这将使用QueryOver完成 – 原因是我dynamic地build立search条件,使用QueryOverstream畅的界面更容易。 (我开始希望使用NHibernate Linq,但不幸的是它还不够成熟)。

经过很多努力(作为NHibernate的相对新手),我能够重新创build内部查询,取得所有的住宿和最低价格。

 public IEnumerable<HolidaySearchDataDto> CriteriaFindAccommodationFromPricesForOffers(IEnumerable<IHolidayFilter<PackageHoliday>> filters, int skip, int take, out bool hasMore) { IQueryOver<PackageHoliday, PackageHoliday> queryable = NHibernateSession.CurrentFor(NHibernateSession.DefaultFactoryKey).QueryOver<PackageHoliday>(); queryable = queryable.Where(h => h.TradeNameId == website.TradeNameID); var accommodation = Null<Accommodation>(); var accommodationUnit = Null<AccommodationUnit>(); var dto = Null<HolidaySearchDataDto>(); // Apply search criteria foreach (var filter in filters) queryable = filter.ApplyFilter(queryable, accommodationUnit, accommodation); var query1 = queryable .JoinQueryOver(h => h.AccommodationUnit, () => accommodationUnit) .JoinQueryOver(h => h.Accommodation, () => accommodation) .SelectList(hols => hols .SelectGroup(() => accommodation.Id).WithAlias(() => dto.AccommodationId) .SelectMin(h => h.Price).WithAlias(() => dto.Price) ); var list = query1.OrderByAlias(() => dto.Price).Asc .Skip(skip).Take(take+1) .Cacheable().CacheMode(CacheMode.Normal).List<object[]>(); // Cacheing doesn't work this way... /*.TransformUsing(Transformers.AliasToBean<HolidaySearchDataDto>()) .Cacheable().CacheMode(CacheMode.Normal).List<HolidaySearchDataDto>();*/ hasMore = list.Count() == take; var dtos = list.Take(take).Select(h => new HolidaySearchDataDto { AccommodationId = (string)h[0], Price = (decimal)h[1], }); return dtos; } 

所以我的问题是…

任何想法如何实现我想要使用QueryOver,或者如果必要的Criteria API?

我宁愿不使用HQL,但是如果有必要的话,我也不愿意看到如何使用HQL(尽pipebuild立search标准更困难(或更加混乱))。

如果这是不可行的使用NHibernate,那么我可以使用SQL查询。 在这种情况下,我的问题是SQL可以改进/优化吗?

我已经设法通过使用Criteria API来实现这样的dynamicsearch标准。 我碰到的问题是与内部和外部联接重复,特别是与sorting和分页有关,我不得不求助于使用2个查询,第一个查询限制,并使用第一个查询的结果作为第二个'in'子句。

Interesting Posts