Pergunta

Eu estou procurando uma maneira de recuperar as linhas "cercam" em uma consulta NHibernate dada uma chave primária e uma ordem de classificação?

por exemplo. Eu tenho uma tabela com entradas de registo e eu quero mostrar a entrada com chave primária 4242 e os anteriores 5 entradas, bem como os seguintes 5 entradas ordenados por data (não há relação direta entre a data ea chave primária). Tal consulta deve retornar 11 linhas no total (desde que não estamos perto de cada extremidade).

A tabela a entrada de log pode ser enorme e recuperar tudo para descobrir isso não é possível.

Existe um conceito como número da linha que pode ser usado a partir de dentro NHibernate? O banco de dados subjacente é ou vai ser SQlite ou Microsoft SQL Server.

Editado Amostra adicionado

Imagine que dados como o seguinte:

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

Ao solicitar a entrada com chave primária 4242 devemos obter as linhas 1237, 1238 e 4239 a 4247. A ordem é por Tempo, Id.

É possível recuperar as entradas em uma única consulta (que, obviamente, pode incluir subconsultas)? O tempo é uma coluna não-exclusivo para várias entradas têm o mesmo valor e, neste exemplo, não é possível alterar a resolução de uma forma que torna! Única

Foi útil?

Solução

"não há relação direta entre a data e primário-chave" significa, que as chaves primárias não estão em ordem sequencial?

Então eu iria fazê-lo como este:

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

Há o risco de ter vários itens com o mesmo tempo.


Editar

Isso deve funcionar agora.

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

Outras dicas

Esta deve ser relativamente fácil com a API Critérios de NHibernate:

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

Aqui o seu listOfIds é apenas uma lista com rigidez de tipos inteiros que representam os ids das entradas que deseja recuperar (inteiros 4242-5 através de 4242 + 5).

É claro que você também pode adicionar Expressions que lhe permitem recuperar IDs maior do que 4242-5 e menor do que 4242 + 5.

A solução de Stefan definitivamente funciona, mas a melhor maneira existe usando um único Subqueries selecionar e aninhados:

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

Esta é NHibernate sintaxe 2.0, mas o mesmo vale para as versões anteriores onde em vez de restrições que você usar a expressão.

Eu testei isso em um aplicativo de teste e funciona como anunciado

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top