SlideShare a Scribd company logo
1 of 10
Download to read offline
Lập trình ứng dụng quản lý 2




Tìm kiếm & phân trang với LINQ to SQL
                            Ngô Ngọc Đăng Khoa
                                      2011, April 26
1    LTUDQL2 – TUT05


    1 Mục tiêu & Yêu cầu
    1.1 Mục tiêu
          Nắm được phương pháp xây dựng chức năng tìm kiếm & phân trang
            trong ứng dụng LINQ to SQL với VB.NET
    1.2 Yêu cầu
          Sinh viên đã hoàn thành tốt 2 tutorial LINQ trước
          Đọc kỹ & thực hiện các bước theo tutorial
    2 Bài tập áp dụng
    2.1 Yêu cầu
         Sử dụng CSDL Northwind, xây dựng chức năng tìm kiếm các sản phẩm đang
    có trong CSDL theo các tiêu chí sau:
          Tên sản phẩm
          Danh mục
          Nhà cung cấp
          Giá
         Kết quả tìm kiếm phải được phân trang (1 trang 10 kết quả) & có dàn nút
    điều hướng trang đầy đủ.
2    LTUDQL2 – TUT05


    2.2 Hướng dẫn
    (Sinh viên sử dụng script CSDL Northwind ở tuần 7)
    Bước 1: Add LINQ to SQL class ứng với CSDL Northwind vào project
    Bước 2: thiết kế giao diện frmMain như hình dưới




    Bước 3: khai báo 1 context toàn cục & đổ dữ liệu vào 2 comboBox
    Dim ctx As New NorthwindDataContext

    Private Sub frmMain_Load(...) Handles MyBase.Load
        Dim listCat As List(Of Category) = ctx.Categories.ToList()
        listCat.Insert(0, New Category With {.CategoryID = -1, .CategoryName = "ALL"})
        cboCat.DataSource = listCat
        cboCat.DisplayMember = "CategoryName"
        cboCat.ValueMember = "CategoryID"

        Dim listSupp As List(Of Supplier) = ctx.Suppliers.ToList()
        listSupp.Insert(0, New Supplier With {.SupplierID = -1, .CompanyName = "ALL"})
        cboSupp.DataSource = listSupp
        cboSupp.DisplayMember = "CompanyName"
        cboSupp.ValueMember = "SupplierID"
    End Sub
3    LTUDQL2 – TUT05


    Bước 4: xây dựng hàm tạo câu truy vấn dựa vào dữ liệu nhập trên các controls
    Function BuildSearchQuery() As IQueryable(Of Product)
        Dim query As IQueryable(Of Product) = ctx.Products

        If txtProductName.Text.Length > 0 Then
            query = query.Where( _
                Function(p) p.ProductName.Contains(txtProductName.Text) _
            )
        End If

        Dim catId As Integer = cboCat.SelectedValue
        If catId > -1 Then
            query = query.Where(Function(p) p.CategoryID = catId)
        End If

        Dim suppId As Integer = cboSupp.SelectedValue
        If suppId > -1 Then
            query = query.Where(Function(p) p.SupplierID = suppId)
        End If

        Dim priceF As Integer = txtPriceF.Value
        If priceF > 0 Then
            query = query.Where(Function(p) p.UnitPrice >= priceF)
        End If

        Dim priceT As Integer = txtPriceT.Value
        If priceT > 0 Then
            query = query.Where(Function(p) p.UnitPrice <= priceT)
        End If

        Return query
    End Function



    Bước 5: xây dựng hàm thực hiện chức năng tìm kiếm
    Private Sub btnSearch_Click(...) Handles btnSearch.Click
        Dim query As IQueryable(Of Product) = BuildSearchQuery()
        grid.DataSource = query
    End Sub



    Bước 6: bổ sung các tham số dùng cho việc chuyển trang (các biến toàn cục)
    Dim ctx As New NorthwindDataContext

    Const PAGE_SIZE As Integer = 10
    Dim curPage As Integer
    Dim numberOfPages As Integer
4    LTUDQL2 – TUT05


    Bước 7: xây dựng hàm điều khiển trạng thái của các nút điều hướng trang
    Sub SetNavigationState()
        btnNext.Enabled = (curPage < numberOfPages)
        btnLast.Enabled = (curPage < numberOfPages)
        btnPrev.Enabled = (curPage > 1)
        btnFirst.Enabled = (curPage > 1)
    End Sub




    Bước 8: bổ sung lời gọi hàm vào hàm frmMain_Load
    Private Sub frmMain_Load(...) Handles MyBase.Load
        Dim listCat As List(Of Category) = ctx.Categories.ToList()
        listCat.Insert(0, New Category With {.CategoryID = -1, .CategoryName = "ALL"})
        cboCat.DataSource = listCat
        cboCat.DisplayMember = "CategoryName"
        cboCat.ValueMember = "CategoryID"

        Dim listSupp As List(Of Supplier) = ctx.Suppliers.ToList()
        listSupp.Insert(0, New Supplier With {.SupplierID = -1, .CompanyName = "ALL"})
        cboSupp.DataSource = listSupp
        cboSupp.DisplayMember = "CompanyName"
        cboSupp.ValueMember = "SupplierID"

        lbPaging.Text = "0/0"
        SetNavigationState()
    End Sub




    Bước 9: sửa hàm btnSearch_Click để ứng dụng lấy dữ liệu đúng trang cần thiết
    & tính toán các tham số cho việc phân trang
    Private Sub btnSearch_Click(...) Handles btnSearch.Click
        Dim query As IQueryable(Of Product) = BuildSearchQuery()
        numberOfPages = Math.Ceiling(query.Count() / PAGE_SIZE)
        curPage = 1
        lbPaging.Text = String.Format("{0}/{1}", curPage, numberOfPages)

        grid.DataSource = query.Skip((curPage - 1) * PAGE_SIZE).Take(PAGE_SIZE)

        SetNavigationState()
    End Sub
5    LTUDQL2 – TUT05


    Bước 10: xây dựng các hàm điều hướng trang, cuối mỗi hàm đều cần gọi lại hàm
    SetNavigationState nhằm chỉnh lại tình trạng của dàn nút điều hướng
    Private Sub btnNext_Click(...) Handles btnNext.Click
        curPage += 1
        lbPaging.Text = String.Format("{0}/{1}", curPage, numberOfPages)
        grid.DataSource = BuildSearchQuery().Skip((curPage - 1) *
    PAGE_SIZE).Take(PAGE_SIZE)

        SetNavigationState()
    End Sub

    Private Sub btnPrev_Click(...) Handles btnPrev.Click
        curPage -= 1
        lbPaging.Text = String.Format("{0}/{1}", curPage, numberOfPages)
        grid.DataSource = BuildSearchQuery().Skip((curPage - 1) *
    PAGE_SIZE).Take(PAGE_SIZE)

        SetNavigationState()
    End Sub

    Private Sub btnLast_Click(...) Handles btnLast.Click
        curPage = numberOfPages
        lbPaging.Text = String.Format("{0}/{1}", curPage, numberOfPages)
        grid.DataSource = BuildSearchQuery().Skip((curPage - 1) *
    PAGE_SIZE).Take(PAGE_SIZE)

        SetNavigationState()
    End Sub

    Private Sub btnFirst_Click(...) Handles btnFirst.Click
        curPage = 1
        lbPaging.Text = String.Format("{0}/{1}", curPage, numberOfPages)
        grid.DataSource = BuildSearchQuery().Skip((curPage - 1) *
    PAGE_SIZE).Take(PAGE_SIZE)

        SetNavigationState()
    End Sub




    Nhận xét: trong các hàm điều hướng, ta nhận thấy đều có lời gọi hàm
    BuildSearchQuery nhằm tạo lại câu truy vấn, điều đó dẫn đến hệ quả người
    dùng có thể thay đổi điều kiện tìm kiếm & bấm vào dàn nút điều hướng để xem
    kết quả truy vấn mới, việc này trong một số trường hợp sẽ dẫn đến lỗi (vd: kết quả
    truy vấn cũ có 4 trang & người dùng đang xem trang 3, người dùng sau đó thay đổi điều
    kiện truy vấn và nhấn Next. Tuy nhiên, kết quả truy vấn mới chỉ có 2 trang & gây ra lỗi).
    Để giải quyết tình trạng trên, ta cần bổ sung 1 số thành phần nhằm đảm bảo
    người dùng chỉ có thể chuyển trang sau khi bấm Search, nếu người dùng thay
    đổi điều kiện tìm kiếm thì họ phải bấm Search & xem kết quả từ trang 1.
6    LTUDQL2 – TUT05


    Bước 11: bổ sung cờ ngăn chặn việc chuyển trang khi chưa bấm Search (biến
    toàn cục)
    '''   <summary>
    '''   Cờ dùng để ngăn các thao tác chuyển trang
    '''   </summary>
    '''   <remarks></remarks>
    Dim   isDirty As Boolean


    Bước 12: thực hiện bật cờ khi người dùng thay đổi các điều kiện tìm kiếm
    Private Sub cboSupp_SelectedIndexChanged(...) ...
        isDirty = True
    End Sub

    Private Sub cboCat_SelectedIndexChanged(...) ...
        isDirty = True
    End Sub

    Private Sub txtProductName_TextChanged(...) ...
        isDirty = True
    End Sub

    Private Sub txtPriceF_ValueChanged(...) ...
        isDirty = True
    End Sub

    Private Sub txtPriceT_ValueChanged(...) ...
        isDirty = True
    End Sub



    Bước 13: xây dựng hàm thông báo lỗi khi chuyển trang mà chưa bấm Search
    Sub RaisePageError()
        MessageBox.Show("Cần thực hiện Search trước khi chuyển trang.", "Error",
    MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
    End Sub
7    LTUDQL2 – TUT05


    Bước 14: thực hiện ngăn thao tác chuyển trang từ đầu
    Private Sub frmMain_Load(...) Handles MyBase.Load
        Dim listCat As List(Of Category) = ctx.Categories.ToList()
        listCat.Insert(0, New Category With {.CategoryID = -1, .CategoryName = "ALL"})
        cboCat.DataSource = listCat
        cboCat.DisplayMember = "CategoryName"
        cboCat.ValueMember = "CategoryID"

        Dim listSupp As List(Of Supplier) = ctx.Suppliers.ToList()
        listSupp.Insert(0, New Supplier With {.SupplierID = -1, .CompanyName = "ALL"})
        cboSupp.DataSource = listSupp
        cboSupp.DisplayMember = "CompanyName"
        cboSupp.ValueMember = "SupplierID"

        isDirty = True 'ngăn ko cho thực hiện các thao tác chuyển trang
        lbPaging.Text = "0/0"
        SetNavigationState()
    End Sub




    Bước 15: bắt đầu đồng ý cho chuyển trang khi người dùng đã nhấn Search
    Private Sub btnSearch_Click(...) Handles btnSearch.Click
        Dim query As IQueryable(Of Product) = BuildSearchQuery()
        numberOfPages = Math.Ceiling(query.Count() / PAGE_SIZE)
        curPage = 1
        lbPaging.Text = String.Format("{0}/{1}", curPage, numberOfPages)

        grid.DataSource = query.Skip((curPage - 1) * PAGE_SIZE).Take(PAGE_SIZE)

        isDirty = False 'bắt đầu cho phép chuyển trang
        SetNavigationState()
    End Sub



    Bước 16: ngăn chặn các thao tác chuyển trang trái phép trong các hàm điều
    hướng trang
    Private Sub btnNext_Click(...) Handles btnNext.Click
        If isDirty Then
            RaisePageError()
            Return
        End If

        curPage += 1
        lbPaging.Text = String.Format("{0}/{1}", curPage, numberOfPages)
        grid.DataSource = BuildSearchQuery().Skip((curPage - 1) *
    PAGE_SIZE).Take(PAGE_SIZE)

        SetNavigationState()
    End Sub
8    LTUDQL2 – TUT05



    Private Sub btnPrev_Click(...) Handles btnPrev.Click
        If isDirty Then
            RaisePageError()
            Return
        End If

        curPage -= 1
        lbPaging.Text = String.Format("{0}/{1}", curPage, numberOfPages)
        grid.DataSource = BuildSearchQuery().Skip((curPage - 1) *
    PAGE_SIZE).Take(PAGE_SIZE)

        SetNavigationState()
    End Sub

    Private Sub btnLast_Click(...) Handles btnLast.Click
        If isDirty Then
            RaisePageError()
            Return
        End If

        curPage = numberOfPages
        lbPaging.Text = String.Format("{0}/{1}", curPage, numberOfPages)
        grid.DataSource = BuildSearchQuery().Skip((curPage - 1) *
    PAGE_SIZE).Take(PAGE_SIZE)

        SetNavigationState()
    End Sub

    Private Sub btnFirst_Click(...) Handles btnFirst.Click
        If isDirty Then
            RaisePageError()
            Return
        End If

        curPage = 1
        lbPaging.Text = String.Format("{0}/{1}", curPage, numberOfPages)
        grid.DataSource = BuildSearchQuery().Skip((curPage - 1) *
    PAGE_SIZE).Take(PAGE_SIZE)

        SetNavigationState()
    End Sub
9    LTUDQL2 – TUT05


    Bước 17: xây dựng hàm Reset form
    Private Sub btnClear_Click(...) Handles btnClear.Click
        txtProductName.Clear()
        txtPriceF.Value = 0
        txtPriceT.Value = 0
        cboCat.SelectedIndex = 0
        cboSupp.SelectedIndex = 0

        grid.DataSource = Nothing

        isDirty = True
        curPage = 0
        numberOfPages = 0
        lbPaging.Text = "0/0"
    End Sub



    3 Phụ lục (sửa câu truy vấn phép chia trong tutorial trước)
        Đề: cho biết danh sách các sinh viên đăng ký tất cả các môn học

        Dim ctx As New QLSVDataContext
        Dim query = ctx.SinhViens.Where( _
            Function(sv) sv.DangKyHocPhans.Distinct().Count() = ctx.MonHocs.Count() _
        )
        grid.DataSource = query

More Related Content

Viewers also liked

Viewers also liked (7)

Les marches-publics
Les marches-publicsLes marches-publics
Les marches-publics
 
Biotecnologia
BiotecnologiaBiotecnologia
Biotecnologia
 
Florbela espanca
Florbela espancaFlorbela espanca
Florbela espanca
 
Mastering Social Media Workshop 3 Sept 2011
Mastering Social Media Workshop 3 Sept 2011Mastering Social Media Workshop 3 Sept 2011
Mastering Social Media Workshop 3 Sept 2011
 
It's Just Love
It's Just LoveIt's Just Love
It's Just Love
 
الهولكوست
الهولكوستالهولكوست
الهولكوست
 
Ejemplos
EjemplosEjemplos
Ejemplos
 

Similar to Hdth09 ltudql02-linq-e3

Hdth07 ltudql02-linq-ep1
Hdth07 ltudql02-linq-ep1Hdth07 ltudql02-linq-ep1
Hdth07 ltudql02-linq-ep1Dũng Đinh
 
Bài 3: Lập trình giao diện điều khiển & Xử lý sự kiện - Lập trình winform - G...
Bài 3: Lập trình giao diện điều khiển & Xử lý sự kiện - Lập trình winform - G...Bài 3: Lập trình giao diện điều khiển & Xử lý sự kiện - Lập trình winform - G...
Bài 3: Lập trình giao diện điều khiển & Xử lý sự kiện - Lập trình winform - G...MasterCode.vn
 
Hướng dẫn lập trình với SCSF phần I (smart client software factory)
Hướng dẫn lập trình với SCSF phần I (smart client software factory)Hướng dẫn lập trình với SCSF phần I (smart client software factory)
Hướng dẫn lập trình với SCSF phần I (smart client software factory)Minh Tri Lam
 
04 chuong 4 - cap nhat du lieu
04   chuong 4 - cap nhat du lieu04   chuong 4 - cap nhat du lieu
04 chuong 4 - cap nhat du lieutruong le hung
 
04 chuong4-capnhatdulieu-140404115156-phpapp02
04 chuong4-capnhatdulieu-140404115156-phpapp0204 chuong4-capnhatdulieu-140404115156-phpapp02
04 chuong4-capnhatdulieu-140404115156-phpapp02huynhtrong774129
 
04 chuong 4 - cap nhat du lieu
04   chuong 4 - cap nhat du lieu04   chuong 4 - cap nhat du lieu
04 chuong 4 - cap nhat du lieutruong le hung
 
BÀI 6: Thủ tục (SUB) và hàm (FUNCTION) - Giáo trình FPT
BÀI 6: Thủ tục (SUB) và hàm (FUNCTION) - Giáo trình FPTBÀI 6: Thủ tục (SUB) và hàm (FUNCTION) - Giáo trình FPT
BÀI 6: Thủ tục (SUB) và hàm (FUNCTION) - Giáo trình FPTMasterCode.vn
 
Web Services
Web ServicesWeb Services
Web Servicesask bills
 
Android Nâng cao-Bài 4: Content Provider
Android Nâng cao-Bài 4: Content ProviderAndroid Nâng cao-Bài 4: Content Provider
Android Nâng cao-Bài 4: Content ProviderPhuoc Nguyen
 
Chuan viet code va thiet ke giao dien trong C#
Chuan viet code va thiet ke giao dien trong C#Chuan viet code va thiet ke giao dien trong C#
Chuan viet code va thiet ke giao dien trong C#Kuli An
 

Similar to Hdth09 ltudql02-linq-e3 (20)

Hdth07 ltudql02-linq-ep1
Hdth07 ltudql02-linq-ep1Hdth07 ltudql02-linq-ep1
Hdth07 ltudql02-linq-ep1
 
LINQ presentation
LINQ presentationLINQ presentation
LINQ presentation
 
Bài 3: Lập trình giao diện điều khiển & Xử lý sự kiện - Lập trình winform - G...
Bài 3: Lập trình giao diện điều khiển & Xử lý sự kiện - Lập trình winform - G...Bài 3: Lập trình giao diện điều khiển & Xử lý sự kiện - Lập trình winform - G...
Bài 3: Lập trình giao diện điều khiển & Xử lý sự kiện - Lập trình winform - G...
 
Hướng dẫn lập trình với SCSF phần I (smart client software factory)
Hướng dẫn lập trình với SCSF phần I (smart client software factory)Hướng dẫn lập trình với SCSF phần I (smart client software factory)
Hướng dẫn lập trình với SCSF phần I (smart client software factory)
 
Asp
AspAsp
Asp
 
04 chuong 4 - cap nhat du lieu
04   chuong 4 - cap nhat du lieu04   chuong 4 - cap nhat du lieu
04 chuong 4 - cap nhat du lieu
 
04 chuong4-capnhatdulieu-140404115156-phpapp02
04 chuong4-capnhatdulieu-140404115156-phpapp0204 chuong4-capnhatdulieu-140404115156-phpapp02
04 chuong4-capnhatdulieu-140404115156-phpapp02
 
04 chuong 4 - cap nhat du lieu
04   chuong 4 - cap nhat du lieu04   chuong 4 - cap nhat du lieu
04 chuong 4 - cap nhat du lieu
 
Aspnet 3.5 _05
Aspnet 3.5 _05Aspnet 3.5 _05
Aspnet 3.5 _05
 
BÀI 6: Thủ tục (SUB) và hàm (FUNCTION) - Giáo trình FPT
BÀI 6: Thủ tục (SUB) và hàm (FUNCTION) - Giáo trình FPTBÀI 6: Thủ tục (SUB) và hàm (FUNCTION) - Giáo trình FPT
BÀI 6: Thủ tục (SUB) và hàm (FUNCTION) - Giáo trình FPT
 
Web Services
Web ServicesWeb Services
Web Services
 
Asp.net003
Asp.net003Asp.net003
Asp.net003
 
Grid view
Grid viewGrid view
Grid view
 
Android Nâng cao-Bài 4: Content Provider
Android Nâng cao-Bài 4: Content ProviderAndroid Nâng cao-Bài 4: Content Provider
Android Nâng cao-Bài 4: Content Provider
 
05 web course form
05 web course   form05 web course   form
05 web course form
 
Giới thiệu Yii Framework 1
Giới thiệu Yii Framework 1Giới thiệu Yii Framework 1
Giới thiệu Yii Framework 1
 
View sp trigger_udf
View sp trigger_udfView sp trigger_udf
View sp trigger_udf
 
Aspnet 3.5 _02
Aspnet 3.5 _02Aspnet 3.5 _02
Aspnet 3.5 _02
 
Chuan viet code va thiet ke giao dien trong C#
Chuan viet code va thiet ke giao dien trong C#Chuan viet code va thiet ke giao dien trong C#
Chuan viet code va thiet ke giao dien trong C#
 
slide_Chuong 3_ (1).ppt
slide_Chuong 3_ (1).pptslide_Chuong 3_ (1).ppt
slide_Chuong 3_ (1).ppt
 

More from Dũng Đinh

Hdth08 ltudql02-linq
Hdth08 ltudql02-linqHdth08 ltudql02-linq
Hdth08 ltudql02-linqDũng Đinh
 
Hdth06 ltudql02-multi languages
Hdth06 ltudql02-multi languagesHdth06 ltudql02-multi languages
Hdth06 ltudql02-multi languagesDũng Đinh
 
Hdth04 ltudql02-dotnet bar
Hdth04 ltudql02-dotnet barHdth04 ltudql02-dotnet bar
Hdth04 ltudql02-dotnet barDũng Đinh
 
Hdth03 ltudql02-user control
Hdth03 ltudql02-user controlHdth03 ltudql02-user control
Hdth03 ltudql02-user controlDũng Đinh
 
Hdth02 ltudql02--tuan02 tt-
Hdth02 ltudql02--tuan02 tt-Hdth02 ltudql02--tuan02 tt-
Hdth02 ltudql02--tuan02 tt-Dũng Đinh
 
Hdth02 ltudql02-su dungsubversion-2
Hdth02 ltudql02-su dungsubversion-2Hdth02 ltudql02-su dungsubversion-2
Hdth02 ltudql02-su dungsubversion-2Dũng Đinh
 
Hdth02 ltudql02-su dungsubversion-1
Hdth02 ltudql02-su dungsubversion-1Hdth02 ltudql02-su dungsubversion-1
Hdth02 ltudql02-su dungsubversion-1Dũng Đinh
 
Hdth01 ltudql2-lap tinhduongdoituong-vb
Hdth01 ltudql2-lap tinhduongdoituong-vbHdth01 ltudql2-lap tinhduongdoituong-vb
Hdth01 ltudql2-lap tinhduongdoituong-vbDũng Đinh
 
Thiet kegiaodien
Thiet kegiaodienThiet kegiaodien
Thiet kegiaodienDũng Đinh
 
07bis.thiet kedulieu
07bis.thiet kedulieu07bis.thiet kedulieu
07bis.thiet kedulieuDũng Đinh
 
06.mo hinhhoayeucau
06.mo hinhhoayeucau06.mo hinhhoayeucau
06.mo hinhhoayeucauDũng Đinh
 
05.thu thapyeucau
05.thu thapyeucau05.thu thapyeucau
05.thu thapyeucauDũng Đinh
 
01.lap trinhhuongdoituong
01.lap trinhhuongdoituong01.lap trinhhuongdoituong
01.lap trinhhuongdoituongDũng Đinh
 

More from Dũng Đinh (18)

Report
ReportReport
Report
 
Linq2 sql
Linq2 sqlLinq2 sql
Linq2 sql
 
Hdth08 ltudql02-linq
Hdth08 ltudql02-linqHdth08 ltudql02-linq
Hdth08 ltudql02-linq
 
Hdth06 ltudql02-multi languages
Hdth06 ltudql02-multi languagesHdth06 ltudql02-multi languages
Hdth06 ltudql02-multi languages
 
Hdth04 ltudql02-dotnet bar
Hdth04 ltudql02-dotnet barHdth04 ltudql02-dotnet bar
Hdth04 ltudql02-dotnet bar
 
Hdth03 ltudql02-user control
Hdth03 ltudql02-user controlHdth03 ltudql02-user control
Hdth03 ltudql02-user control
 
Hdth02 ltudql02--tuan02 tt-
Hdth02 ltudql02--tuan02 tt-Hdth02 ltudql02--tuan02 tt-
Hdth02 ltudql02--tuan02 tt-
 
Hdth02 ltudql02-su dungsubversion-2
Hdth02 ltudql02-su dungsubversion-2Hdth02 ltudql02-su dungsubversion-2
Hdth02 ltudql02-su dungsubversion-2
 
Hdth02 ltudql02-su dungsubversion-1
Hdth02 ltudql02-su dungsubversion-1Hdth02 ltudql02-su dungsubversion-1
Hdth02 ltudql02-su dungsubversion-1
 
Hdth01 ltudql2-lap tinhduongdoituong-vb
Hdth01 ltudql2-lap tinhduongdoituong-vbHdth01 ltudql2-lap tinhduongdoituong-vb
Hdth01 ltudql2-lap tinhduongdoituong-vb
 
Thiet kegiaodien
Thiet kegiaodienThiet kegiaodien
Thiet kegiaodien
 
07bis.thiet kedulieu
07bis.thiet kedulieu07bis.thiet kedulieu
07bis.thiet kedulieu
 
06.mo hinhhoayeucau
06.mo hinhhoayeucau06.mo hinhhoayeucau
06.mo hinhhoayeucau
 
05.thu thapyeucau
05.thu thapyeucau05.thu thapyeucau
05.thu thapyeucau
 
04.mo daucnpm
04.mo daucnpm04.mo daucnpm
04.mo daucnpm
 
03.ke thua daxa
03.ke thua daxa03.ke thua daxa
03.ke thua daxa
 
02.thiet kelop
02.thiet kelop02.thiet kelop
02.thiet kelop
 
01.lap trinhhuongdoituong
01.lap trinhhuongdoituong01.lap trinhhuongdoituong
01.lap trinhhuongdoituong
 

Hdth09 ltudql02-linq-e3

  • 1. Lập trình ứng dụng quản lý 2 Tìm kiếm & phân trang với LINQ to SQL Ngô Ngọc Đăng Khoa 2011, April 26
  • 2. 1 LTUDQL2 – TUT05 1 Mục tiêu & Yêu cầu 1.1 Mục tiêu  Nắm được phương pháp xây dựng chức năng tìm kiếm & phân trang trong ứng dụng LINQ to SQL với VB.NET 1.2 Yêu cầu  Sinh viên đã hoàn thành tốt 2 tutorial LINQ trước  Đọc kỹ & thực hiện các bước theo tutorial 2 Bài tập áp dụng 2.1 Yêu cầu Sử dụng CSDL Northwind, xây dựng chức năng tìm kiếm các sản phẩm đang có trong CSDL theo các tiêu chí sau:  Tên sản phẩm  Danh mục  Nhà cung cấp  Giá Kết quả tìm kiếm phải được phân trang (1 trang 10 kết quả) & có dàn nút điều hướng trang đầy đủ.
  • 3. 2 LTUDQL2 – TUT05 2.2 Hướng dẫn (Sinh viên sử dụng script CSDL Northwind ở tuần 7) Bước 1: Add LINQ to SQL class ứng với CSDL Northwind vào project Bước 2: thiết kế giao diện frmMain như hình dưới Bước 3: khai báo 1 context toàn cục & đổ dữ liệu vào 2 comboBox Dim ctx As New NorthwindDataContext Private Sub frmMain_Load(...) Handles MyBase.Load Dim listCat As List(Of Category) = ctx.Categories.ToList() listCat.Insert(0, New Category With {.CategoryID = -1, .CategoryName = "ALL"}) cboCat.DataSource = listCat cboCat.DisplayMember = "CategoryName" cboCat.ValueMember = "CategoryID" Dim listSupp As List(Of Supplier) = ctx.Suppliers.ToList() listSupp.Insert(0, New Supplier With {.SupplierID = -1, .CompanyName = "ALL"}) cboSupp.DataSource = listSupp cboSupp.DisplayMember = "CompanyName" cboSupp.ValueMember = "SupplierID" End Sub
  • 4. 3 LTUDQL2 – TUT05 Bước 4: xây dựng hàm tạo câu truy vấn dựa vào dữ liệu nhập trên các controls Function BuildSearchQuery() As IQueryable(Of Product) Dim query As IQueryable(Of Product) = ctx.Products If txtProductName.Text.Length > 0 Then query = query.Where( _ Function(p) p.ProductName.Contains(txtProductName.Text) _ ) End If Dim catId As Integer = cboCat.SelectedValue If catId > -1 Then query = query.Where(Function(p) p.CategoryID = catId) End If Dim suppId As Integer = cboSupp.SelectedValue If suppId > -1 Then query = query.Where(Function(p) p.SupplierID = suppId) End If Dim priceF As Integer = txtPriceF.Value If priceF > 0 Then query = query.Where(Function(p) p.UnitPrice >= priceF) End If Dim priceT As Integer = txtPriceT.Value If priceT > 0 Then query = query.Where(Function(p) p.UnitPrice <= priceT) End If Return query End Function Bước 5: xây dựng hàm thực hiện chức năng tìm kiếm Private Sub btnSearch_Click(...) Handles btnSearch.Click Dim query As IQueryable(Of Product) = BuildSearchQuery() grid.DataSource = query End Sub Bước 6: bổ sung các tham số dùng cho việc chuyển trang (các biến toàn cục) Dim ctx As New NorthwindDataContext Const PAGE_SIZE As Integer = 10 Dim curPage As Integer Dim numberOfPages As Integer
  • 5. 4 LTUDQL2 – TUT05 Bước 7: xây dựng hàm điều khiển trạng thái của các nút điều hướng trang Sub SetNavigationState() btnNext.Enabled = (curPage < numberOfPages) btnLast.Enabled = (curPage < numberOfPages) btnPrev.Enabled = (curPage > 1) btnFirst.Enabled = (curPage > 1) End Sub Bước 8: bổ sung lời gọi hàm vào hàm frmMain_Load Private Sub frmMain_Load(...) Handles MyBase.Load Dim listCat As List(Of Category) = ctx.Categories.ToList() listCat.Insert(0, New Category With {.CategoryID = -1, .CategoryName = "ALL"}) cboCat.DataSource = listCat cboCat.DisplayMember = "CategoryName" cboCat.ValueMember = "CategoryID" Dim listSupp As List(Of Supplier) = ctx.Suppliers.ToList() listSupp.Insert(0, New Supplier With {.SupplierID = -1, .CompanyName = "ALL"}) cboSupp.DataSource = listSupp cboSupp.DisplayMember = "CompanyName" cboSupp.ValueMember = "SupplierID" lbPaging.Text = "0/0" SetNavigationState() End Sub Bước 9: sửa hàm btnSearch_Click để ứng dụng lấy dữ liệu đúng trang cần thiết & tính toán các tham số cho việc phân trang Private Sub btnSearch_Click(...) Handles btnSearch.Click Dim query As IQueryable(Of Product) = BuildSearchQuery() numberOfPages = Math.Ceiling(query.Count() / PAGE_SIZE) curPage = 1 lbPaging.Text = String.Format("{0}/{1}", curPage, numberOfPages) grid.DataSource = query.Skip((curPage - 1) * PAGE_SIZE).Take(PAGE_SIZE) SetNavigationState() End Sub
  • 6. 5 LTUDQL2 – TUT05 Bước 10: xây dựng các hàm điều hướng trang, cuối mỗi hàm đều cần gọi lại hàm SetNavigationState nhằm chỉnh lại tình trạng của dàn nút điều hướng Private Sub btnNext_Click(...) Handles btnNext.Click curPage += 1 lbPaging.Text = String.Format("{0}/{1}", curPage, numberOfPages) grid.DataSource = BuildSearchQuery().Skip((curPage - 1) * PAGE_SIZE).Take(PAGE_SIZE) SetNavigationState() End Sub Private Sub btnPrev_Click(...) Handles btnPrev.Click curPage -= 1 lbPaging.Text = String.Format("{0}/{1}", curPage, numberOfPages) grid.DataSource = BuildSearchQuery().Skip((curPage - 1) * PAGE_SIZE).Take(PAGE_SIZE) SetNavigationState() End Sub Private Sub btnLast_Click(...) Handles btnLast.Click curPage = numberOfPages lbPaging.Text = String.Format("{0}/{1}", curPage, numberOfPages) grid.DataSource = BuildSearchQuery().Skip((curPage - 1) * PAGE_SIZE).Take(PAGE_SIZE) SetNavigationState() End Sub Private Sub btnFirst_Click(...) Handles btnFirst.Click curPage = 1 lbPaging.Text = String.Format("{0}/{1}", curPage, numberOfPages) grid.DataSource = BuildSearchQuery().Skip((curPage - 1) * PAGE_SIZE).Take(PAGE_SIZE) SetNavigationState() End Sub Nhận xét: trong các hàm điều hướng, ta nhận thấy đều có lời gọi hàm BuildSearchQuery nhằm tạo lại câu truy vấn, điều đó dẫn đến hệ quả người dùng có thể thay đổi điều kiện tìm kiếm & bấm vào dàn nút điều hướng để xem kết quả truy vấn mới, việc này trong một số trường hợp sẽ dẫn đến lỗi (vd: kết quả truy vấn cũ có 4 trang & người dùng đang xem trang 3, người dùng sau đó thay đổi điều kiện truy vấn và nhấn Next. Tuy nhiên, kết quả truy vấn mới chỉ có 2 trang & gây ra lỗi). Để giải quyết tình trạng trên, ta cần bổ sung 1 số thành phần nhằm đảm bảo người dùng chỉ có thể chuyển trang sau khi bấm Search, nếu người dùng thay đổi điều kiện tìm kiếm thì họ phải bấm Search & xem kết quả từ trang 1.
  • 7. 6 LTUDQL2 – TUT05 Bước 11: bổ sung cờ ngăn chặn việc chuyển trang khi chưa bấm Search (biến toàn cục) ''' <summary> ''' Cờ dùng để ngăn các thao tác chuyển trang ''' </summary> ''' <remarks></remarks> Dim isDirty As Boolean Bước 12: thực hiện bật cờ khi người dùng thay đổi các điều kiện tìm kiếm Private Sub cboSupp_SelectedIndexChanged(...) ... isDirty = True End Sub Private Sub cboCat_SelectedIndexChanged(...) ... isDirty = True End Sub Private Sub txtProductName_TextChanged(...) ... isDirty = True End Sub Private Sub txtPriceF_ValueChanged(...) ... isDirty = True End Sub Private Sub txtPriceT_ValueChanged(...) ... isDirty = True End Sub Bước 13: xây dựng hàm thông báo lỗi khi chuyển trang mà chưa bấm Search Sub RaisePageError() MessageBox.Show("Cần thực hiện Search trước khi chuyển trang.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) End Sub
  • 8. 7 LTUDQL2 – TUT05 Bước 14: thực hiện ngăn thao tác chuyển trang từ đầu Private Sub frmMain_Load(...) Handles MyBase.Load Dim listCat As List(Of Category) = ctx.Categories.ToList() listCat.Insert(0, New Category With {.CategoryID = -1, .CategoryName = "ALL"}) cboCat.DataSource = listCat cboCat.DisplayMember = "CategoryName" cboCat.ValueMember = "CategoryID" Dim listSupp As List(Of Supplier) = ctx.Suppliers.ToList() listSupp.Insert(0, New Supplier With {.SupplierID = -1, .CompanyName = "ALL"}) cboSupp.DataSource = listSupp cboSupp.DisplayMember = "CompanyName" cboSupp.ValueMember = "SupplierID" isDirty = True 'ngăn ko cho thực hiện các thao tác chuyển trang lbPaging.Text = "0/0" SetNavigationState() End Sub Bước 15: bắt đầu đồng ý cho chuyển trang khi người dùng đã nhấn Search Private Sub btnSearch_Click(...) Handles btnSearch.Click Dim query As IQueryable(Of Product) = BuildSearchQuery() numberOfPages = Math.Ceiling(query.Count() / PAGE_SIZE) curPage = 1 lbPaging.Text = String.Format("{0}/{1}", curPage, numberOfPages) grid.DataSource = query.Skip((curPage - 1) * PAGE_SIZE).Take(PAGE_SIZE) isDirty = False 'bắt đầu cho phép chuyển trang SetNavigationState() End Sub Bước 16: ngăn chặn các thao tác chuyển trang trái phép trong các hàm điều hướng trang Private Sub btnNext_Click(...) Handles btnNext.Click If isDirty Then RaisePageError() Return End If curPage += 1 lbPaging.Text = String.Format("{0}/{1}", curPage, numberOfPages) grid.DataSource = BuildSearchQuery().Skip((curPage - 1) * PAGE_SIZE).Take(PAGE_SIZE) SetNavigationState() End Sub
  • 9. 8 LTUDQL2 – TUT05 Private Sub btnPrev_Click(...) Handles btnPrev.Click If isDirty Then RaisePageError() Return End If curPage -= 1 lbPaging.Text = String.Format("{0}/{1}", curPage, numberOfPages) grid.DataSource = BuildSearchQuery().Skip((curPage - 1) * PAGE_SIZE).Take(PAGE_SIZE) SetNavigationState() End Sub Private Sub btnLast_Click(...) Handles btnLast.Click If isDirty Then RaisePageError() Return End If curPage = numberOfPages lbPaging.Text = String.Format("{0}/{1}", curPage, numberOfPages) grid.DataSource = BuildSearchQuery().Skip((curPage - 1) * PAGE_SIZE).Take(PAGE_SIZE) SetNavigationState() End Sub Private Sub btnFirst_Click(...) Handles btnFirst.Click If isDirty Then RaisePageError() Return End If curPage = 1 lbPaging.Text = String.Format("{0}/{1}", curPage, numberOfPages) grid.DataSource = BuildSearchQuery().Skip((curPage - 1) * PAGE_SIZE).Take(PAGE_SIZE) SetNavigationState() End Sub
  • 10. 9 LTUDQL2 – TUT05 Bước 17: xây dựng hàm Reset form Private Sub btnClear_Click(...) Handles btnClear.Click txtProductName.Clear() txtPriceF.Value = 0 txtPriceT.Value = 0 cboCat.SelectedIndex = 0 cboSupp.SelectedIndex = 0 grid.DataSource = Nothing isDirty = True curPage = 0 numberOfPages = 0 lbPaging.Text = "0/0" End Sub 3 Phụ lục (sửa câu truy vấn phép chia trong tutorial trước) Đề: cho biết danh sách các sinh viên đăng ký tất cả các môn học Dim ctx As New QLSVDataContext Dim query = ctx.SinhViens.Where( _ Function(sv) sv.DangKyHocPhans.Distinct().Count() = ctx.MonHocs.Count() _ ) grid.DataSource = query