• Thứ Sáu, 12/03/2004 09:44 (GMT+7)

    Nâng cấp ứng dụng Visual FoxPro

    Bạn đang sử dụng ứng dụng viết bằng Visual FoxPro và muốn nâng cấp nó để có thể truy cập các hệ cơ sở dữ liệu lớn như SQL Server hay Oracle nhằm khai thác khả năng xử lý trên mạng, khả năng bảo mật... Bài viết này giới thiệu với các bạn một số phương pháp, thủ thuật để thực hiện.

    Với các ứng dụng chạy trên máy đơn và số lượng bản ghi ít (dưới 10.000 bản ghi - record), hệ cơ sở dữ liệu (CSDL) của Visual FoxPro (VFP) đáp ứng hiệu quả. Khi số lượng giao dịch tăng lên, bạn có nhu cầu dùng ứng dụng trên mạng và đặc biệt là cần khả năng bảo mật và tính toàn vẹn dữ liệu cao thì các hệ CSDL lớn như MS SQL Server hay Oracle mới có thể đáp ứng yêu cầu. Nhờ tính linh hoạt và mềm dẻo của VFP, bạn có thể dễ dàng nâng cấp ứng dụng viết bằng VFP để truy cập vào SQL Server, Oracle... mà không phải lập trình lại ứng dụng trên các ngôn ngữ khác.

    Thiết kế form nhập dữ liệu với view

    Trong VFP, View là một câu lệnh SQL được lưu trữ trong CSDL và được chia làm 2 loại: Local Views được dùng để truy cập dữ liệu của VFP, Remote Views dùng để truy cập bất kỳ nguồn dữ liệu nào tương thích với ODBC. Với sự bổ sung của View trong VFP bạn có thể làm việc với nhiều hệ CSDL khác nhau cùng một cách thức.

    Khi thiết kế các form nhập dữ liệu cho ứng dụng VFP client/server, bạn có thể sử dụng SQL Pass-throught (SPT), một cách đơn giản để đưa chuỗi lệnh SQL thông qua ODBC đến nguồn dữ liệu, hoặc bạn có thể dùng Remote Views, một dạng phát biểu SQL được lưu trong Database Container (DBC) của VFP.

    Bằng cách gọi hàm SQLEXEC, SPT đặt kết quả vào một con trỏ cục bộ (cursor), và bạn có thể quét qua từng đối tượng trên form để gán giá trị (dạng như: thisform.txtKhachhang.Value = SQLResult.Khachhang). Sau đó, để thao tác dữ liệu trên server, bạn cần tạo các câu lệnh SQL Update, Insert, Delete. Đây cũng là cách thường dùng trong Visual Basic. Đoạn code dưới đây minh hoạ cách truy cập bằng SPT vào CSDL SQL Server WebTool đã được khai báo ở ODBC Data Source Administrator:

    * Thủ tục này mở bảng bw_loaivanban trong database WebTool, đặt kết quả vào cursor
    *  Result_lvb

       hConn = SQLCONNECT('webtool','sa', 'sa') && sa/sa: username/pwd

     sSQL = 'SELECT maloai, tenloai FROM bw_loaivanban'

                SQLEXEC(hConn, sSQL, 'result_lvb')

                thisform.txtmaloai.value = result_lvb.maloai

                ...

    * Thủ tục này cập nhật bảng bw_loaivanban tại bản ghi có maloai = pK

                sSQL = 'UPDATE bw_loaivanban SET tenloai = 'abcd' WHERE ' + ;

                            ' maloai = '' + pK + '' '

                SQLEXEC(hConn, sSQL)

    * Lệnh sau giải phóng mối kết nối với SQL Server

                SQLDISCONNECT(hConn)

    Nếu sử dụng Remote Views, công việc tạo form nhập liệu sẽ đơn giản hơn nhiều, bạn chỉ cần tạo một View có cấu trúc giống như bảng bạn cần cập nhật, xây dựng form trên nền View vừa tạo giống như thao tác trên các bảng của VFP. Để cập nhật, bạn dùng phương pháp TableUpdate để tạo tự động các câu lệnh SQL Update, Insert, Delete tương ứng và gửi tới trình quản lý ODBC tại máy trạm. Trình điều khiển ODBC mà bạn đã khai báo sẽ dịch sang câu lệnh SQL phù hợp với cú pháp của hệ CSDL và gửi đến server để thi hành.
    Theo kinh nghiệm, bạn nên sử dụng Remote Views cho các form nhập liệu vì cách này sẽ giảm rất nhiều công sức viết mã lệnh, có thể dùng chung mã lệnh cho các bảng của VFP cũng như SQL Server, Oracle,.. và tốc độ thực thi cũng nhanh hơn, ít xảy ra lỗi và dễ tìm lỗi (debug) hơn.

    Sử dụng thủ tục lưu sẵn trên RDBMS và câu truy vấn có tham số

    Để tăng tốc độ thi hành câu lệnh trong ứng dụng client/server, không có gì hiệu quả bằng cách sử dụng các thủ tục lưu sẵn trên CSDL (Stored Procedure - SP). Khi sử dụng SP, bạn nên lưu ý cách đưa tham số vào của từng hệ CSDL có khác nhau. Ví dụ như đoạn lệnh sau thi hành thủ tục bw_GetLoaiVB với tham số là mã loại:

    SQLEXEC('bw_GetLoaiVB('01')')                 && Doi voi VFP table

                SQLEXEC('bw_GetLoaiVB '01' ')                  && Doi voi SQL Server

    Để ứng dụng có thể chạy được trên nhiều hệ CSDL khác nhau, bạn có thể gọi thi hành SP thông qua một hàm tự tạo, trong đó xét từng hệ CSDL để có cú pháp tương ứng.

    Nếu không thích dùng SP, bạn có thể sử dụng câu truy vấn có tham số (Parameterized Query - PQ) được lưu sẵn trong ứng dụng. Với PQ, bạn không phải lo đến cú pháp gọi SP đã lưu ở hệ CSDL và không phải viết lại SP cho từng hệ CSDL khác nhau. Một PQ có dạng:

                cmaloai = '01'

                fSuccess = SQLEXEC(hConn, 'Select * from bw_Loaivanban ;

                   Where maloai = ?cmaloai', 'rLoaiVB')

    Bạn sẽ thấy rất thuận tiện khi sử dụng PQ vì phần lớn các hệ CSDL đều hỗ  trợ cú pháp này, hơn nữa bạn sẽ tránh các phiền hà khi kết nối chuỗi dạng ' '' + cmaloai + '' ', đặc biệt là trong trường hợp cmaloai có chứa các dấu ' '.Trong trường hợp bạn tạo các câu truy vấn phức tạp và không cần phải cập nhật dữ liệu (như khi bạn tạo báo cáo đầu ra), bạn nên sử dụng SP hoặc SPT thay cho View để tăng tốc độ hệ thống, đặc biệt là đối với các CSDL lớn.

    Hạn chế kết quả trả về của câu truy vấn

    Trong ứng dụng client/server, các bản ghi trả về sau khi thi hành câu truy vấn sẽ được truyền từ server đến máy trạm cục bộ, vì vậy bạn cần quan tâm giảm thiểu lượng dữ liệu phải truyền qua đường mạng, điều đó vừa giảm nhu cầu tài nguyên của ứng dụng, vừa tăng tốc độ thực hiện. Giả sử, ứng dụng của bạn cần chỉnh sửa các đơn hàng của 1 khách hàng trong 10.000 đơn hàng có trong CSDL, bạn không nên lấy hết các đơn hàng về rồi tìm các đơn hàng cần trong số đó để chỉnh sửa mà bạn nên gửi lệnh đến server chọn riêng các đơn hàng thoả điều kiện yêu cầu. Đoạn lệnh sau minh hoạ việc chọn lựa trên:

    * Tạo View

                Create SQL View vDonhang AS Select * From donhang ;

                            Where ma_KH = ?cMa_KH

    * Khi nạp form (Load), bạn mở View này ở trạng thái không có dữ liệu

                Use vDonhang NoData

                ...
    * Lấy các đơn hàng của khách hàng có mã số người dùng đã nhập ở txtMaKH

                cMa_KH = thisform.txtMaKH.Value

                ReQuery()       

    Một vài lưu ý khác

    o    Dùng Locate thay vì Seek: Khi thao tác trên dữ liệu kết quả của câu lệnh SQL trong ứng dụng client/server, bạn mất đi một khả năng rất tiện dụng mà người lập trình VFP thường dùng là SEEK. Thay vào đó, bạn phải dùng LOCATE. Vì vậy, để đảm bảo tốc độ cho ứng dụng, bạn nên lưu ý hạn chế dữ liệu tìm kiếm để thực hiện câu lệnh được nhanh hơn.

    o    Sử dụng khoá chính cho các bảng: khi sử dụng các View để cập nhật dữ liệu bạn phải có một khoá chính (primary key) cho bảng tương ứng. Khi sử dụng các câu lệnh SQL, các cột làm khoá chính sẽ rất hữu ích để đơn giản hoá việc tạo câu truy vấn, tìm kiếm bản ghi để cập nhật, xoá, tăng tốc độ trong câu truy vấn có kết nối nhiều bảng. Trong kiến trúc client/server bạn sẽ thường xuyên sử dụng khả năng này.

       Sử dụng dữ liệu kiểu ngày tháng: Phần lớn các hệ CSDL lớn, như SQL server, không hỗ trợ kiểu dữ liệu ngày-tháng (Date), mà sử dụng kiểu dữ liệu ngày-tháng-giờ (DateTime). Nếu bạn chuyển ứng dụng VFP có sử dụng dữ liệu kiểu ngày tháng sang dùng SQL Server bạn cần để ý đến việc bỏ đi phần thời gian nằm phía sau cột dữ liệu ngày tháng. Khi gắn (bound) các đối tượng trên form vào các cột dữ liệu dạng ngày-tháng, bạn có thể dùng DBSetProp để thay đổi loại dữ liệu từ DateTime sang Date khi định nghĩa View (hoặc bạn có thể thay đổi phần Data mapping trong giao diện Modify View của VFP). Một lưu ý nữa là hầu hết các CSDL client/server không cho phép bạn đặt giá trị rỗng trong cột chứa dữ liệu kiểu DateTime, mà phải chứa một giá trị ngày-tháng-giờ hợp lệ hoặc là Null.

    Hy vọng bài viết này sẽ giúp được bạn lựa chọn giải pháp, cũng như có thêm một số thủ thuật để nâng cấp ứng dụng VFP của mình.ÿ

    Thái Lương Hùng
    Phòng xử lý thông tin và tin học -  Cục thuế tỉnh Bình Định
    email: thailuonghung@yahoo.com

    ID: A0402_91