คุณจะทำเพจด้วย NHibernate ได้อย่างไร?


107

ตัวอย่างเช่นฉันต้องการเติมข้อมูลตัวควบคุม gridview ในเว็บเพจ ASP.NET โดยมีเฉพาะข้อมูลที่จำเป็นสำหรับจำนวนแถวที่แสดง NHibernate รองรับสิ่งนี้ได้อย่างไร?

คำตอบ:


111

ICriteriaมีSetFirstResult(int i)วิธีการที่ระบุดัชนีของรายการแรกที่คุณต้องการได้รับ (โดยทั่วไปคือแถวข้อมูลแรกในหน้าของคุณ)

นอกจากนี้ยังมีSetMaxResults(int i)วิธีการซึ่งระบุจำนวนแถวที่คุณต้องการได้รับ (เช่นขนาดหน้าของคุณ)

ตัวอย่างเช่นวัตถุเกณฑ์นี้จะได้รับผลลัพธ์ 10 รายการแรกของตารางข้อมูลของคุณ:

criteria.SetFirstResult(0).SetMaxResults(10);

1
นี่เป็นสิ่งที่ไวยากรณ์ Linq (ถึง NH) จะมีลักษณะเหมือนกัน - Nice
MotoWilliams

13
โปรดทราบว่าคุณจะต้องดำเนินธุรกรรมแยกต่างหากเพื่อดึงจำนวนแถวทั้งหมดเพื่อแสดงเพจเจอร์ของคุณ
Kevin Pang

1
ดำเนินการแบบสอบถาม SELECT TOP ใน SQL Server ลองใช้ SetFirstResult (1). SetMaxResult (2);
Chris S

4
นั่นคือความคิดเห็นก่อนหน้านี้ใช้ NHibernate.Dialect.MsSql2000Dialect ไม่ใช่ NHibernate.Dialect.MsSql2005Dialect
Chris S

IQuery มีฟังก์ชันเดียวกันดังนั้นจึงสามารถใช้กับ HQL ได้เช่นกัน
goku_da_master

87

คุณยังสามารถใช้ประโยชน์จากคุณสมบัติ Futures ใน NHibernate เพื่อดำเนินการค้นหาเพื่อรับจำนวนเรกคอร์ดทั้งหมดรวมทั้งผลลัพธ์จริงในแบบสอบถามเดียว

ตัวอย่าง

 // Get the total row count in the database.
var rowCount = this.Session.CreateCriteria(typeof(EventLogEntry))
    .Add(Expression.Between("Timestamp", startDate, endDate))
    .SetProjection(Projections.RowCount()).FutureValue<Int32>();

// Get the actual log entries, respecting the paging.
var results = this.Session.CreateCriteria(typeof(EventLogEntry))
    .Add(Expression.Between("Timestamp", startDate, endDate))
    .SetFirstResult(pageIndex * pageSize)
    .SetMaxResults(pageSize)
    .Future<EventLogEntry>();

ในการรับจำนวนเรกคอร์ดทั้งหมดให้ทำดังต่อไปนี้:

int iRowCount = rowCount.Value;

การสนทนาที่ดีของสิ่งที่ฟิวเจอร์สให้คุณคือที่นี่


3
นี่มันเยี่ยมมาก ฟิวเจอร์สทำงานเหมือนกับหลายเกณฑ์โดยไม่มีความซับซ้อนทางไวยากรณ์ของหลายเกณฑ์
DavGarcia

หลังจากอ่านโพสต์เกี่ยวกับ Futures แล้วฉันก็สงสัยว่าฉันควรใช้ Future สำหรับการสืบค้นฐานข้อมูลทั้งหมดของฉันหรือไม่ ... มีข้อเสียอย่างไร? :)
hakksor

46

จาก NHibernate 3 ขึ้นไปคุณสามารถใช้QueryOver<T>:

var pageRecords = nhSession.QueryOver<TEntity>()
            .Skip((PageNumber - 1) * PageSize)
            .Take(PageSize)
            .List();

คุณอาจต้องการจัดลำดับผลลัพธ์ของคุณอย่างชัดเจนดังนี้:

var pageRecords = nhSession.QueryOver<TEntity>()
            .OrderBy(t => t.AnOrderFieldLikeDate).Desc
            .Skip((PageNumber - 1) * PageSize)
            .Take(PageSize)
            .List();

.Skip(PageNumber * PageSize)ด้วยวิธีนี้หากขนาดหน้าเป็น 10 จะไม่ดึงข้อมูล 10 แถวแรก ฉันกำลังแก้ไขเพื่อให้สูตรถูกต้อง สมมติว่าตามแนวคิดPageNumberไม่ควรเป็น 0 ควรต่ำสุด 1
Amit Joshi

31
public IList<Customer> GetPagedData(int page, int pageSize, out long count)
        {
            try
            {
                var all = new List<Customer>();

                ISession s = NHibernateHttpModule.CurrentSession;
                IList results = s.CreateMultiCriteria()
                                    .Add(s.CreateCriteria(typeof(Customer)).SetFirstResult(page * pageSize).SetMaxResults(pageSize))
                                    .Add(s.CreateCriteria(typeof(Customer)).SetProjection(Projections.RowCountInt64()))
                                    .List();

                foreach (var o in (IList)results[0])
                    all.Add((Customer)o);

                count = (long)((IList)results[1])[0];
                return all;
            }
            catch (Exception ex) { throw new Exception("GetPagedData Customer da hata", ex); }
      }

เมื่อข้อมูลเพจมีวิธีอื่นในการรับผลลัพธ์ที่พิมพ์จาก MultiCriteria หรือทุกคนทำแบบเดียวกันกับฉัน?

ขอบคุณ


23

วิธีการใช้ Linq กับ NHibernate ตามที่กล่าวไว้ในบล็อกโพสต์นี้โดย Ayende

ตัวอย่างโค้ด:

(from c in nwnd.Customers select c.CustomerID)
        .Skip(10).Take(10).ToList(); 

และนี่คือโพสต์โดยละเอียดโดยบล็อกของทีม NHibernate เกี่ยวกับการเข้าถึงข้อมูลด้วย NHibernateรวมถึงการใช้เพจจิ้ง


หมายเหตุ linq ถึง Nhibernate อยู่ในแพ็คเกจ Contrib และไม่รวมอยู่ในรุ่น NHibernate 2.0
Richard

11

เป็นไปได้มากที่สุดใน GridView คุณจะต้องการแสดงส่วนของข้อมูลบวกจำนวนแถวทั้งหมด (จำนวนแถว) ของจำนวนข้อมูลทั้งหมดที่ตรงกับคำค้นหาของคุณ

คุณควรใช้ MultiQuery เพื่อส่งทั้งแบบสอบถาม Select count (*) และแบบสอบถาม. SetFirstResult (n). SetMaxResult (m) ไปยังฐานข้อมูลของคุณในการโทรครั้งเดียว

โปรดทราบว่าผลลัพธ์จะเป็นรายการที่มี 2 รายการรายการหนึ่งสำหรับชิ้นข้อมูลและอีกรายการสำหรับการนับ

ตัวอย่าง:

IMultiQuery multiQuery = s.CreateMultiQuery()
    .Add(s.CreateQuery("from Item i where i.Id > ?")
            .SetInt32(0, 50).SetFirstResult(10))
    .Add(s.CreateQuery("select count(*) from Item i where i.Id > ?")
            .SetInt32(0, 50));
IList results = multiQuery.List();
IList items = (IList)results[0];
long count = (long)((IList)results[1])[0];

6

ฉันขอแนะนำให้คุณสร้างโครงสร้างเฉพาะเพื่อจัดการกับการแบ่งหน้า บางอย่างเช่น (ฉันเป็นโปรแกรมเมอร์ Java แต่ควรจะแมปได้ง่าย):

public class Page {

   private List results;
   private int pageSize;
   private int page;

   public Page(Query query, int page, int pageSize) {

       this.page = page;
       this.pageSize = pageSize;
       results = query.setFirstResult(page * pageSize)
           .setMaxResults(pageSize+1)
           .list();

   }

   public List getNextPage()

   public List getPreviousPage()

   public int getPageCount()

   public int getCurrentPage()

   public void setPageSize()

}

ฉันไม่ได้ให้การใช้งาน แต่คุณสามารถใช้วิธีการที่@Jonแนะนำได้ นี่คือการสนทนาที่ดีสำหรับคุณที่จะดู


0

คุณไม่จำเป็นต้องกำหนด 2 เกณฑ์คุณสามารถกำหนดหนึ่งเกณฑ์และโคลนได้ ในการโคลนเกณฑ์ nHibernate คุณสามารถใช้รหัสง่ายๆ:

var criteria = ... (your criteria initializations)...;
var countCrit = (ICriteria)criteria.Clone();
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.