Kamil Kliczbor @ asptip.net

6Jan/112

101 przykładów zapytań w NHibernate 3.x – HQL, Criteria API, QueryOver i Linq – Sortowanie

Wprowadzenie

Wpis ten jest częścią artykułu poświęconemu wykonywaniu zapytań w NHibernate przy użyciu różnych sposobów jakie udostępnia ten mapper - HQL, Criteria API, QueryOver i Linq.

Część ta opisuje stosowanie sortowania danych w zapytaniach. Jeżeli piszesz instrukcję SELECT zachodzi czasem konieczność uporządkowania danych, które są zwracane w wyniku zapytania. Ogólnie rzecz biorąc stosujemy w SQL słowo ORDER BY wraz z opcjonalnym ASC|DESC oznaczającym kierunek sortowania. Koncepcję użycia przedstawiam poniżej:

SELECT Co FROM NazwaObiektu ORDER BY NazwaColumny [ASC|DESC], NazwaInnejKolumny [ASC|DESC]

Spis zapytań

Do poczytania

Prosty przykład

SQL

SELECT   this_.ProductId       as ProductId6_0_,
         this_.ProductName     as ProductN2_6_0_,
         this_.QuantityPerUnit as Quantity3_6_0_,
         this_.UnitPrice       as UnitPrice6_0_,
         this_.UnitsInStock    as UnitsInS5_6_0_,
         this_.UnitsOnOrder    as UnitsOnO6_6_0_,
         this_.ReorderLevel    as ReorderL7_6_0_,
         this_.Discontinued    as Disconti8_6_0_,
         this_.SupplierId      as SupplierId6_0_,
         this_.CategoryId      as CategoryId6_0_
FROM     Products this_
ORDER BY this_.ProductName asc

Zapytania

// HQL
this.Session.CreateQuery("from Product p order by p.Name")
    .List<Product>();

// ICriteria API (1)
this.Session.CreateCriteria(typeof(Product))
    .AddOrder(Order.Asc("Name"))
    .List<Product>();

// ICriteria API (2)
this.Session.CreateCriteria<Product>()
    .AddOrder<Product>(x => x.Name, Order.Asc)
    .List<Product>();

// QueryOver
this.Session.QueryOver<Product>()
    .OrderBy(x => x.Name).Asc
    .List<Product>();

// LINQ (1)
this.Session
    .Query<Product>()
    .OrderBy(x => x.Name)
    .ToList();

// LINQ (2)
var query = from p in this.Session.Query<Product>()
            orderby p.Name
            select p;
query.ToList();

Sortowanie po długości wartości

SQL

select   product0_.ProductId       as ProductId6_,
         product0_.ProductName     as ProductN2_6_,
         product0_.QuantityPerUnit as Quantity3_6_,
         product0_.UnitPrice       as UnitPrice6_,
         product0_.UnitsInStock    as UnitsInS5_6_,
         product0_.UnitsOnOrder    as UnitsOnO6_6_,
         product0_.ReorderLevel    as ReorderL7_6_,
         product0_.Discontinued    as Disconti8_6_,
         product0_.SupplierId      as SupplierId6_,
         product0_.CategoryId      as CategoryId6_
from     Products product0_
order by len(product0_.ProductName)

Zapytania

// HQL
this.Session.CreateQuery("from Product p order by len(p.Name)")
    .List<Product>();

// ICriteria API
// not possible

// QueryOver
// not possible

// LINQ (1)
this.Session
    .Query<Product>()
    .OrderBy(x => x.Name.Length)
    .ToList();

// LINQ (2)
var query = from p in this.Session.Query<Product>()
            orderby p.Name.Length
            select p;
query.ToList();

Sortowanie po kilku kolumnach

SQL

SELECT   this_.ProductId       as ProductId6_0_,
         this_.ProductName     as ProductN2_6_0_,
         this_.QuantityPerUnit as Quantity3_6_0_,
         this_.UnitPrice       as UnitPrice6_0_,
         this_.UnitsInStock    as UnitsInS5_6_0_,
         this_.UnitsOnOrder    as UnitsOnO6_6_0_,
         this_.ReorderLevel    as ReorderL7_6_0_,
         this_.Discontinued    as Disconti8_6_0_,
         this_.SupplierId      as SupplierId6_0_,
         this_.CategoryId      as CategoryId6_0_
FROM     Products this_
ORDER BY this_.ProductName asc,
         this_.QuantityPerUnit desc,
         this_.Discontinued asc

Zapytania

// HQL
this.Session.CreateQuery("from Product p order by p.Name asc, p.QuantityPerUnit desc, p.Discontinued")
    .List<Product>();

// ICriteria API (1)
this.Session.CreateCriteria(typeof(Product))
    .AddOrder(Order.Asc("Name"))
    .AddOrder(Order.Desc("QuantityPerUnit"))
    .AddOrder(Order.Asc("Discontinued"))
    .List<Product>();

// ICriteria API (2)
this.Session.CreateCriteria<Product>()
    .AddOrder<Product>(x => x.Name, Order.Asc)
    .AddOrder<Product>(x => x.QuantityPerUnit, Order.Desc)
    .AddOrder<Product>(x => x.Discontinued, Order.Asc)
    .List<Product>();

// QueryOver
this.Session.QueryOver<Product>()
    .OrderBy(x => x.Name).Asc
    .OrderBy(x => x.QuantityPerUnit).Desc
    .OrderBy(x => x.Discontinued).Asc
    .List<Product>();

// LINQ (1)
this.Session
    .Query<Product>()
    .OrderBy(x => x.Name)
    .ThenByDescending(x => x.QuantityPerUnit)
    .ThenBy(x => x.Discontinued)
    .ToList();

// LINQ (2)
var query = from p in this.Session.Query<Product>()
            orderby p.Name, p.QuantityPerUnit descending, p.Discontinued
            select p;
query.ToList();

Sortowanie po kilku kolumnach przez alias (różne tabele)

SQL

SELECT   this_.ProductId           as ProductId6_1_,
         this_.ProductName         as ProductN2_6_1_,
         this_.QuantityPerUnit     as Quantity3_6_1_,
         this_.UnitPrice           as UnitPrice6_1_,
         this_.UnitsInStock        as UnitsInS5_6_1_,
         this_.UnitsOnOrder        as UnitsOnO6_6_1_,
         this_.ReorderLevel        as ReorderL7_6_1_,
         this_.Discontinued        as Disconti8_6_1_,
         this_.SupplierId          as SupplierId6_1_,
         this_.CategoryId          as CategoryId6_1_,
         categoryal1_.CategoryId   as CategoryId5_0_,
         categoryal1_.CategoryName as Category2_5_0_,
         categoryal1_.Description  as Descript3_5_0_
FROM     Products this_
         inner join Categories categoryal1_
           on this_.CategoryId = categoryal1_.CategoryId
ORDER BY this_.ProductName desc,
         categoryal1_.CategoryName asc

Zapytania

// HQL
this.Session.CreateQuery("from Product p join p.Category c order by p.Name desc, c.Name")
    .List<Product>();

// ICriteria API (1)
this.Session.CreateCriteria(typeof(Product))
    .CreateAlias("Category", "categoryAlias")
    .AddOrder(Order.Desc("Name"))
    .AddOrder(Order.Asc("categoryAlias.Name"))
    .List<Product>();

ProductCategory categoryAlias = null;

// ICriteria API (2)
this.Session.CreateCriteria<Product>()
    .CreateAlias<Product>(x => x.Category, () => categoryAlias)
    .AddOrder<Product>(x => x.Name, Order.Desc)
    .AddOrder<ProductCategory>(x => categoryAlias.Name, Order.Asc)
    .List<Product>();

// QueryOver
 /* ThenByAlias and OrderByAlias are supposed to work with projections properties.
               You should distinguish between OrderBy ad orderByAlias methods. */
this.Session.QueryOver<Product>()
    .OrderBy(x => x.Name).Desc
    .JoinQueryOver(x => x.Category, () => categoryAlias)
    .OrderBy(x => x.Name).Asc
    .List<Product>();

// LINQ (1)
this.Session
    .Query<Product>()
    .OrderByDescending(x => x.Name)
    .ThenBy(x => x.Category.Name)
    .ToList();

// LINQ (2)
var query = from p in this.Session.Query<Product>()
            orderby p.Name descending, p.Category.Name
            select p;
query.ToList();
Comments (2) Trackbacks (0)
  1. Witam,

    myślę, że dobrze zacząłeś od najprostszych zapytań. Proponuję przejść do trudniejszych np. tworzenie prostych podsumowań np. z wykorzystaniem .selectGroup .selectCount .TransformUsing(Transformers.aliastobean). Oprócz tego mógłbyś pokazać użycie podzapytań w wyszukiwaniu .WithSubquery. Proponowałbym także dodać taki mocno rozbudowany przykład z wyszukiwaniem po wielu kryteriach nie tylko filtrując po kolumnach z jednej tabeli, ale tworząc podzapytania.

    Parę przykładów oczywiście mogę podać od ręki.


    Pozdrawiam,
    Maciek

    • Cześć Maciek,
      cieszę się, ze tutaj ktoś zagląda :)
      Dziękuję za wskazówki. Tak jak sobie próbuję to wszystko ogarnąć, to bardzo ciężko jest odseparować każdy z wariantów zadawania pytań. Staram się w miarę je klarownie przedstawiać, jednakże często te sposoby na siebie zachodzą. Np. jak chciałem przedstawić sortowanie na podstawie aliasu z innej encji, to musiałem niestety użyć joina, którego jeszcze nie prezentowałem.
      W zamyśle chciałbym przejść przez różne możliwe typy zapytań, z uwzględnieniem tego, żeby przedstawić je w miarę prosty sposób. Dzięki takiemu zabiegowi będzie można się do nich odnieść i (tak sobie życzę) swobodnie łączyć.
      Chciałem tylko podkreślić, że podczas pisania tych przykładów znalazłem dwa bugi, które zgłosiłem w projekcie.


Leave a comment

No trackbacks yet.