문제

기본 키와 정렬 순서가 주어진 nhibernate 쿼리에서 "주변"행을 검색하는 방법을 찾고 있습니까?

예를 들어 로그 항목이있는 테이블이 있으며 기본 키 4242 및 이전 5 개의 항목이있는 항목과 날짜별로 주문한 5 개의 항목을 표시하고 싶습니다 (날짜와 기본 키 사이에는 직접적인 관계가 없습니다). 이러한 쿼리는 총 11 행을 반환해야합니다 (우리가 양쪽 끝에 가깝지 않은 한).

로그 엔트리 테이블은 거대 할 수 있으며 파악하기 위해 모든 것을 검색하는 것은 불가능합니다.

nhibernate 내에서 사용할 수있는 행 번호와 같은 개념이 있습니까? 기본 데이터베이스는 SQLITE 또는 Microsoft SQL Server가 될 것입니다.

편집 추가 샘플

다음과 같은 데이터를 상상해보십시오.

Id   Time
4237 10:00
4238 10:00
1236 10:01
1237 10:01
1238 10:02
4239 10:03
4240 10:04
4241 10:04
4242 10:04   <-- requested "center" row
4243 10:04
4244 10:05
4245 10:06
4246 10:07
4247 10:08

기본 키 4242로 항목을 요청할 때 1237, 1238 및 4239 ~ 4247 행을 가져와야합니다. 순서는 시간에 따른 ID입니다.

단일 쿼리에서 항목을 검색 할 수 있습니까 (하위 쿼리를 포함 할 수 있음)? 시간은 비 유니크 열이므로 여러 항목이 동일한 값을 가지며이 예에서는 독특한 방식으로 해상도를 변경할 수 없습니다!

도움이 되었습니까?

해결책

"날짜와 기본 키 사이에 직접적인 관계가 없다"는 기본 키가 순차적 순서가 아니라고 의미합니까?

그런 다음 이렇게 할 것입니다.

Item middleItem = Session.Get(id);

IList<Item> previousFiveItems = Session.CreateCriteria((typeof(Item))
  .Add(Expression.Le("Time", middleItem.Time))
  .AddOrder(Order.Desc("Time"))
  .SetMaxResults(5);

IList<Item> nextFiveItems = Session.CreateCriteria((typeof(Item))
  .Add(Expression.Gt("Time", middleItem.Time))
  .AddOrder(Order.Asc("Time"))
  .SetMaxResults(5);

동시에 여러 품목을 가질 위험이 있습니다.


편집하다

이것은 지금 작동해야합니다.

Item middleItem = Session.Get(id);

IList<Item> previousFiveItems = Session.CreateCriteria((typeof(Item))
  .Add(Expression.Le("Time", middleItem.Time)) // less or equal
  .Add(Expression.Not(Expression.IdEq(middleItem.id))) // but not the middle
  .AddOrder(Order.Desc("Time"))
  .SetMaxResults(5);

IList<Item> nextFiveItems = Session.CreateCriteria((typeof(Item))
  .Add(Expression.Gt("Time", middleItem.Time))  // greater 
  .AddOrder(Order.Asc("Time"))
  .SetMaxResults(5);

다른 팁

Nhibernate의 기준 API에서는 비교적 쉬워야합니다.

List<LogEntry> logEntries = session.CreateCriteria(typeof(LogEntry))
.Add(Expression.InG<int>(Projections.Property("Id"), listOfIds))
.AddOrder(Order.Desc("EntryDate"))
.List<LogEntry>();

여기 당신의 listOfIds 검색하려는 항목의 ID를 나타내는 정수 목록입니다 (정수 4242-5 ~ 4242+5).

물론 추가 할 수도 있습니다 Expressions 이를 통해 4242-5보다 큰 ID를 4242+5보다 작게 검색 할 수 있습니다.

Stefan의 솔루션은 확실히 작동하지만 단일 선택 및 중첩 하위 쿼리를 사용하여 더 나은 방법이 있습니다.

ICriteria crit = NHibernateSession.CreateCriteria(typeof(Item));

        DetachedCriteria dcMiddleTime =
            DetachedCriteria.For(typeof(Item)).SetProjection(Property.ForName("Time"))
            .Add(Restrictions.Eq("Id", id));

        DetachedCriteria dcAfterTime =
            DetachedCriteria.For(typeof(Item)).SetMaxResults(5).SetProjection(Property.ForName("Id"))
            .Add(Subqueries.PropertyGt("Time", dcMiddleTime));
        DetachedCriteria dcBeforeTime =
            DetachedCriteria.For(typeof(Item)).SetMaxResults(5).SetProjection(Property.ForName("Id"))
                .Add(Subqueries.PropertyLt("Time", dcMiddleTime));

        crit.AddOrder(Order.Asc("Time"));
        crit.Add(Restrictions.Eq("Id", id) || Subqueries.PropertyIn("Id", dcAfterTime) ||
                 Subqueries.PropertyIn("Id", dcBeforeTime));

        return crit.List<Item>();

이것은 nhibernate 2.0 구문이지만 제한 대신 표현식을 사용하는 이전 버전에서도 마찬가지입니다.

테스트 응용 프로그램에서 이것을 테스트했으며 광고대로 작동합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top