Sử dụng đối tượng kết nối ADO và tập bản ghi. Sử dụng thư viện ADO (Đối tượng dữ liệu Microsoft ActiveX). Tạo cơ sở dữ liệu MS Access

Chương trong cuốn sách của Marco Cantu: Delphi 7. Dành cho các chuyên gia
Các tác giả cảm ơn nhà xuất bản PITER vì những tài liệu được cung cấp để xuất bản.

Tóm tắt của nhà xuất bản

Môi trường Delphi đã và vẫn là sự kết hợp tốt nhất giữa lập trình hướng đối tượng và lập trình trực quan, không chỉ cho Windows mà bây giờ còn cho Linux và trong tương lai gần cho .NET. Trong cuốn sách này, tác giả đã cố gắng loại bỏ gần như hoàn toàn tài liệu tham khảo, tập trung vào các công nghệ sử dụng Delphi hiệu quả. Cuốn sách chứa hơn 300 ví dụ. Như một người đăng ký nhóm tin đã nói, “Sách của Cantú về cơ bản đã được lọc qua Delphi, chỉ lớn hơn và hay hơn.” Cuốn sách dành cho các lập trình viên, nhà phát triển và bất kỳ ai quan tâm nghiêm túc đến việc lập trình trong môi trường Delphi.

Công nghệ ADO (Chương 15)

Từ giữa những năm 1980, các lập trình viên RDBMS đã cố gắng tìm ra “chìa khóa thần kỳ” mở ra cánh cửa dẫn đến vùng đất độc lập khỏi một cơ sở dữ liệu cụ thể. Vấn đề là dữ liệu có thể đến từ nhiều nguồn khác nhau, mỗi nguồn đều có những đặc điểm riêng. Tuy nhiên, việc phát triển ứng dụng sẽ được đơn giản hóa rất nhiều nếu có thể tạo ra một cơ chế thống nhất để tương tác với nhiều nguồn dữ liệu khác nhau. Đây có thể là một phần mềm phổ quát Giao diện API, điều này sẽ cho phép các lập trình viên phát triển các ứng dụng tương tác với các nguồn dữ liệu khác nhau theo cùng một cách. Các ứng dụng như vậy có thể được sử dụng để tương tác với chính các hệ thống RDBMS khác nhau cũng như các nguồn dữ liệu khác. Trong thời gian qua, nhiều công ty đã đề xuất nhiều giải pháp trong lĩnh vực này. Đáng kể nhất là Microsoft ODBC (Kết nối cơ sở dữ liệu mở) và Borland IDAPI (Giao diện lập trình ứng dụng cơ sở dữ liệu tích hợp). Công nghệ Borland IDAPI được biết đến nhiều hơn với cái tên BDE (Công cụ cơ sở dữ liệu Borland).
Vào giữa những năm 1990, với sự phát triển và lan rộng của COM (Component Mô hình đối tượng), Microsoft đã công bố chuyển đổi dần dần từ ODBC sang sử dụng công nghệ OLE DB mới. Tuy nhiên, OLE DB, theo chính Microsoft, là một giao diện cấp hệ thống nên được các lập trình viên hệ thống sử dụng. Công nghệ OLE DB nặng, phức tạp và rất nhạy cảm với lỗi. Nó đòi hỏi quá nhiều từ người lập trình. Làm việc với OLE DB quá khó. Để làm việc với OLE DB dễ dàng hơn, một bổ sung lớp ứng dụng, được gọi là ADO (Đối tượng dữ liệu ActiveX). Làm việc với ADO dễ dàng hơn nhiều so với làm việc với OLE DB. Công nghệ ADO dành cho các lập trình viên ứng dụng.
Như đã thảo luận ở Chương 14, Borland cũng quyết định thay thế BDE bằng một công nghệ mới gọi là dbExpress. Cần lưu ý rằng ADO gợi nhớ đến BDE nhiều hơn về khả năng và hệ tư tưởng của nó. Cả BDE và ADO đều hỗ trợ điều hướng, thao tác tập dữ liệu, xử lý giao dịch, cập nhật được lưu trong bộ nhớ đệm (trong ADO, chúng được gọi là cập nhật hàng loạt). Nói cách khác, về mặt khái niệm và ý thức hệ, ADO và BDE là những công nghệ tương tự nhau.

GHI CHÚ

Tôi xin cảm ơn Guy Smith Ferrier đã viết chương này cho cuốn sách Mastering Delphi 6. Guy là một lập trình viên, tác giả của nhiều cuốn sách và bài báo, đồng thời cũng là diễn giả tại các hội nghị. Ông là tác giả của nhiều sản phẩm phần mềm thương mại và nhiều sản phẩm phần mềm thương mại. hệ thống nội bộ cho cả các công ty nhỏ và lớn. Ông đã viết nhiều bài báo cho Tạp chí The Delphi cũng như các ấn phẩm khác. Ngoài ra, ông còn phát biểu tại nhiều hội nghị khác nhau ở Bắc Mỹ và Châu Âu. Guy sống ở Anh cùng vợ, con trai và con mèo.

Trong chương này chúng ta sẽ xem xét cách làm việc với ADO. Chúng ta cũng sẽ xem xét dbGo, một tập hợp các thành phần Delphi ban đầu được gọi là ADOExpress nhưng đã được đổi tên trong Delphi 6 vì Microsoft phản đối việc sử dụng ký hiệu ADO trong các sản phẩm của bên thứ ba. Trong môi trường Delphi, bạn có thể làm việc với ADO mà không cần sự trợ giúp của dbGo. Bạn có thể nhập thư viện loại ADO và truy cập trực tiếp vào giao diện ADO. Đây là cách bạn đã từng làm việc với ADO ở Delphi trước Delphi 5. Tuy nhiên, cách tiếp cận này không cho phép bạn tận dụng cơ sở hạ tầng cơ sở dữ liệu tích hợp của Delphi. Cụ thể, bạn sẽ không thể sử dụng các điều khiển dành riêng cho dữ liệu và bạn sẽ không có quyền truy cập vào công nghệ DataSnap. Tất cả các ví dụ trong chương này đều sử dụng dbGo để tương tác với ADO. Thứ nhất, dbGo được bao gồm trong gói Delphi tiêu chuẩn và thứ hai, dbGo là một công nghệ rất tiện lợi. Cho dù bạn chọn sử dụng dbGo hay không, bạn sẽ thấy tài liệu trong chương này hữu ích.

GHI CHÚ

Ngoài dbGo, bạn có thể sử dụng nhiều sản phẩm khác của bên thứ ba để tương tác với ADO, chẳng hạn như Adonis, AdoSlutio, Diamond ADO và Kamiak.

Chương này bao gồm các chủ đề sau:

    Thành phần truy cập dữ liệu của Microsoft (MDAC);

  • Tệp liên kết dữ liệu;

    thu thập thông tin về chương trình;

    sử dụng cơ chế phản lực;

    xử lý giao dịch;

    các tập bản ghi bị vô hiệu hóa và được lưu trữ trên đĩa;

    mô hình danh mục đầu tư và thiết lập MDAC.

MDAC (Thành phần truy cập dữ liệu của Microsoft)

ADO thực sự là một phần của công nghệ lớn hơn được gọi là Cấu phần truy cập dữ liệu của Microsoft (MDAC). Thuật ngữ MDAC là tên gọi chung cho tất cả các công nghệ liên quan đến cơ sở dữ liệu do Microsoft phát triển. Bộ này bao gồm ADO, OLE DB, ODBC và RDS (Dịch vụ dữ liệu từ xa). Bạn thường nghe người ta sử dụng thuật ngữ MDAC và ADO thay thế cho nhau, nhưng điều này không chính xác. Trên thực tế, ADO chỉ là một phần của MDAC. Khi nói về các phiên bản ADO, chúng tôi muốn nói đến các phiên bản MDAC. Các phiên bản chính của MDAC bao gồm các phiên bản 1.5, 2.0, 2.1, 2.5 và 2.6. Microsoft phân phối MDAC dưới dạng một sản phẩm riêng biệt. Sản phẩm này có thể được tải xuống miễn phí từ trang web của Microsoft. Không chỉ vậy, nó còn thực sự có thể được đưa vào sản phẩm của bạn miễn phí (có hạn chế nhất định, tuy nhiên, hầu hết các nhà phát triển Delphi đều đáp ứng tất cả các yêu cầu này mà không gặp vấn đề gì). Ngoài ra, MDAC được bao gồm trong hầu hết các sản phẩm cơ sở dữ liệu của Microsoft. Delphi 7 bao gồm MDAC 2.6.
Hai trường hợp quan trọng phải được tính đến. Đầu tiên, chúng tôi có thể tự tin nói rằng công nghệ MDAC đã được cài đặt trên máy khách của người dùng của bạn. Thứ hai, bất kể phiên bản MDAC nào đã được cài đặt trên máy khách của người dùng của bạn, có thể nói rằng phiên bản này sớm hay muộn sẽ được cập nhật lên phiên bản MDAC (hiện tại) mới nhất. Việc cập nhật có thể được thực hiện bởi bạn, người dùng của bạn hoặc một trong các hệ thống được cài đặt Ứng dụng của Microsoft. Bản cập nhật như vậy hầu như không thể ngăn chặn được vì MDAC được cài đặt như một phần của ứng dụng được sử dụng rộng rãi như Internet Explorer. Cần nói thêm rằng Microsoft chỉ hỗ trợ phiên bản MDAC mới nhất và cũng là phiên bản sớm hơn phiên bản mới nhất. Dựa trên tất cả những điều này, chúng tôi có thể đi đến kết luận: ứng dụng của bạn phải hoạt động với phiên bản MDAC mới nhất hoặc với phiên bản trước đó.
Là nhà phát triển ADO, bạn nên thường xuyên xem lại các trang MDAC trên trang Web của Microsoft. Để thực hiện việc này, vui lòng liên hệ với www. microsoft.com/data. Tại đây bạn có thể tải xuống miễn phí phiên bản MDAC mới nhất. Bạn cũng nên tải xuống MDAC SDK (13 MB) nếu bạn chưa có gói này. Trên thực tế, SDK MDAC được bao gồm trong SDK nền tảng, vì vậy nếu bạn có SDK nền tảng thì bạn đã có SDK MDAC. Hãy để MDAC SDK trở thành kinh thánh của bạn. Bạn nên tải xuống và tham khảo thường xuyên để có được thông tin bạn cần và trả lời mọi câu hỏi liên quan đến ADO. Nếu bạn cần thông tin liên quan đến MDAC, nơi đầu tiên bạn nên tìm là MDAC SDK.

Nhà cung cấp OLE DB

Các nhà cung cấp OLE DB cung cấp quyền truy cập vào các nguồn dữ liệu. dbExpress sử dụng trình điều khiển cho mục đích này, trong khi BDE sử dụng Liên kết SQL. Trong quá trình cài đặt MDAC, các nhà cung cấp OLE DB được liệt kê trong Bảng 1 sẽ được cài đặt tự động trên hệ thống. 15.1.

Bảng 15.1. Nhà cung cấp OLE DB có trong MDAC

Tài xế

Các nhà cung cấp

Sự miêu tả

Trình điều khiển ODBC (Mặc định)

Microsoft.Jet.OLEDB.3.5

Chỉ cơ sở dữ liệu MS Access 97

Microsoft.Jet.OLEDB.4.0

Cơ sở dữ liệu MS Access và các cơ sở dữ liệu khác

Cơ sở dữ liệu máy chủ MS SQL

Cơ sở dữ liệu Oracle

Xử lý phân tích trực tuyến

Ví dụ về nhà cung cấp OLE DB cho tệp CSV

Để tạo nhà cung cấp của riêng bạn cho dữ liệu văn bản thuần túy

Dưới đây là danh sách các nhà cung cấp này.

    ODBC OLE DB được sử dụng để tương thích ngược với ODBC. Khi xem xét kỹ hơn cách thức hoạt động của ADO, bạn sẽ tìm hiểu về những hạn chế cố hữu của nhà cung cấp này.

    Jet OLE DB - hỗ trợ cho MS Access và các cơ sở dữ liệu cục bộ khác. Chúng tôi sẽ quay lại xem xét các nhà cung cấp này dưới đây.

    SQL Server cung cấp khả năng tương tác với SQL Server 7, SQL Server 2000 và Microsoft Database Engine (MSDE). MSDE là phiên bản đơn giản hóa của SQL Server loại bỏ hầu hết các công cụ và thêm mã đặc biệt cố tình làm giảm hiệu suất nếu có hơn năm người dùng kết nối với cơ sở dữ liệu cùng một lúc. Ưu điểm của MSDE bao gồm cơ chế này được phân phối miễn phí và hoàn toàn tương thích với SQL Server.

    OLE DB cho OLAP có thể được sử dụng trực tiếp nhưng được truy cập phổ biến hơn thông qua ADO Multi-Dimental (ADOMD). ADOMD là công nghệ ADO bổ sung được thiết kế đặc biệt cho Xử lý phân tích trực tuyến (OLAP). Nếu trước đây bạn đã làm việc với Khối quyết định Delphi, Bảng tổng hợp Excel hoặc Tab chéo Access thì bạn đã làm việc với một trong các biểu mẫu OLAP. Ngoài các nhà cung cấp đã được liệt kê ở đây, Microsoft còn hỗ trợ một số nhà cung cấp OLE DB khác được bao gồm trong các sản phẩm khác hoặc như một phần của SDK.

    Dịch vụ Active Directory OLE DB được bao gồm trong ADSI SDK; AS/400 OLE DB và VSAM OLE DB được tích hợp trong SNA Server; Exchange OLE DB được bao gồm trong Microsoft Exchange 2000.

    Dịch vụ lập chỉ mục OLE DB là một phần của Dịch vụ lập chỉ mục của Microsoft - một cơ chế nội bộ của Windows giúp tăng tốc độ tìm kiếm thông tin trong tệp bằng cách xây dựng thư mục chứa thông tin tệp. Dịch vụ lập chỉ mục được tích hợp vào IIS và thường được sử dụng để lập chỉ mục các trang Web.

    Internet Publishing OLE DB cho phép các nhà phát triển thao tác các thư mục và tệp bằng HTTP.

    Ngoài ra còn có một loại nhà cung cấp OLE DB được gọi là nhà cung cấp dịch vụ. Đúng như tên gọi, các nhà cung cấp này cung cấp dịch vụ cho các nhà cung cấp OLE DB khác và thường được kích hoạt tự động mà không cần sự can thiệp của lập trình viên. Ví dụ: Dịch vụ con trỏ được kích hoạt nếu bạn tạo một con trỏ ở phía máy khách và Nhà cung cấp bộ bản ghi liên tục được kích hoạt nếu bạn có ý định lưu trữ dữ liệu trên đĩa cục bộ.

Ngoài những cái được liệt kê, còn có một số lượng lớn các nhà cung cấp OLE DB khác cho MDAC. Nhà cung cấp OLE DB có sẵn từ cả Microsoft và nhà cung cấp bên thứ ba. Danh sách các nhà cung cấp OLE DB rất lớn và thay đổi liên tục nên không thể sao chép lại trong cuốn sách này. Ngoài các nhà cung cấp độc lập, nhiều nhà cung cấp RDBMS còn cung cấp và hỗ trợ các nhà cung cấp OLE DB. Ví dụ: Oracle duy trì nhà cung cấp OLE DB của riêng mình có tên ORAOLEDB.

Có thể bạn đã nhận thấy rằng nhà cung cấp OLE DB cho InterBase bị thiếu trong danh sách. Thứ nhất, bạn có thể sử dụng trình điều khiển ODBC và thứ hai, bạn có thể sử dụng nhà cung cấp IBProvider do Dmitry Kovalenko phát triển (www.lipetsk.ru/prog/eng/index.html). Cuối cùng, bạn có thể cố gắng tự mình phát triển nhà cung cấp. Một cách thuận tiện để thực hiện việc này là sử dụng Bộ công cụ phát triển nhà cung cấp OLE DB, do Bình Lý phát triển và có sẵn tại http://www.techvanguards.com/products/optk/install.htm.

Sử dụng các thành phần dbGo

Những lập trình viên đã quen với BDE, dbExpess hay IBExpress sẽ dễ dàng nhận ra các thành phần có trong dbGo (Bảng 15.2).

Bảng 15.2. thành phần dbGo

thành phần dbGo

Sự miêu tả

Tương đương với bộ BDE

Kết nối với cơ sở dữ liệu

Cơ sở dữ liệu

Thực thi lệnh SQL

Không có tương đương

Hậu duệ đa năng của TDataSet

Không có tương đương

Đóng gói một bảng

Đóng gói SQL CHỌN

Đóng gói một thủ tục được lưu trữ

Kết nối dịch vụ dữ liệu từ xa

Không có tương đương

Bốn thành phần tập dữ liệu (ADODataSet, ADOTable, ADOQuery và ADOStoredProc) thực tế được triển khai hoàn toàn bởi một lớp cơ sở chung, TCustomADODataSet. Thành phần này chịu trách nhiệm thực hiện hầu hết các chức năng vốn có trong tập dữ liệu. Các thành phần phái sinh là những lớp vỏ mỏng giúp cung cấp một số khả năng nhất định của thành phần cơ sở với thế giới bên ngoài. Vì vậy, các thành phần có nhiều đặc điểm chung. Các thành phần ADOTable, ADOQuery và ADOStoredProc được thiết kế để giúp điều chỉnh mã nhắm mục tiêu BDE dễ dàng hơn. Tuy nhiên, cần lưu ý rằng các thành phần này không thể được coi là tương đương hoàn toàn giống với các thành phần BDE tương tự. Sự khác biệt chắc chắn sẽ bộc lộ khi phát triển hầu như bất kỳ ứng dụng nào, ngoại trừ những ứng dụng tầm thường nhất. Thành phần ADODataSet nên được coi là thành phần chính khi phát triển các chương trình mới, vì thứ nhất, thành phần này khá tiện lợi và thứ hai, giao diện của nó tương tự như giao diện ADO Recordset. Trong chương này, tôi sẽ trình bày cách sử dụng từng thành phần được đề cập.

Nghiên cứu điển hình

Lý thuyết đủ rồi, hãy bắt tay vào công việc. Hãy đặt thành phần ADOTable trên biểu mẫu. ADO sử dụng chuỗi kết nối để chỉ ra cơ sở dữ liệu nào cần kết nối. Nếu bạn biết mình đang làm gì, bạn có thể nhập chuỗi kết nối theo cách thủ công. Tuy nhiên, nói chung, để tạo chuỗi kết nối, nên sử dụng một trình soạn thảo đặc biệt (trình soạn thảo thuộc tính ConnectionString), cửa sổ làm việc của nó được hiển thị trong Hình. 15.1.

Nhấp vào Build để khởi chạy trình chỉnh sửa chuỗi kết nối của Microsoft. Cửa sổ làm việc của nó được hiển thị trong hình. 15.2. Chúng ta hãy xem xét kỹ hơn công cụ này vì nó là một công cụ quan trọng khi làm việc với ADO. Tab đầu tiên hiển thị các nhà cung cấp OLE DB và nhà cung cấp dịch vụ được cài đặt trên máy tính của bạn. Danh sách các nhà cung cấp có thể khác nhau đối với các phiên bản MDAC khác nhau, ngoài ra, các nhà cung cấp mới có thể xuất hiện trong danh sách do cài đặt các chương trình ứng dụng mới trên máy tính. Hãy quay trở lại ví dụ của chúng tôi. Chọn Nhà cung cấp Jet 4.0 OLE DB bằng cách nhấp đúp vào Nhà cung cấp Jet 4.0 OLE DB và tab Kết nối sẽ xuất hiện trên màn hình. Sự xuất hiện của trang này có thể khác nhau đối với các nhà cung cấp khác nhau. Đối với nhà cung cấp Jet, trình chỉnh sửa sẽ nhắc bạn nhập tên cơ sở dữ liệu và thông tin xác thực. Bạn có thể chọn tệp MDB cơ sở dữ liệu Access đi kèm với Delphi (ví dụ: C:\Program Files\Common Files\Borland Shared\Data\dbdemos.mdb). Bấm vào Nút kiểm tra Kết nối để đảm bảo lựa chọn của bạn là chính xác.
Trên tab Nâng cao, bạn có thể kiểm soát chế độ truy cập cơ sở dữ liệu. Tại đây bạn có thể thiết lập quyền truy cập độc quyền hoặc chỉ đọc. Tab Tất cả liệt kê tất cả các tham số chuỗi kết nối. Danh sách này có thể khác nhau đối với các nhà cung cấp OLE DB khác nhau. Hãy nhớ kỹ trang này vì nó có thể được sử dụng để giải quyết nhiều vấn đề khác nhau. Đóng Microsoft Editor sẽ đưa bạn trở lại trình giảm chuỗi kết nối Borland. Cửa sổ làm việc của trình soạn thảo này sẽ hiển thị chuỗi sẽ được gán cho ConnectionString (ở đây tôi chia thành nhiều dòng để dễ đọc hơn):

Nhà cung cấp=Microsoft.Jet.OLEDB.4.0; Nguồn dữ liệu=C:\Program Files\Common Files\Borland Shared\Data\dbdemos.mdb; Thông tin bảo mật liên tục = Sai


Chuỗi kết nối là một chuỗi ký tự đơn giản liệt kê các tham số và giá trị của chúng, được phân tách bằng dấu chấm phẩy. Dòng này có thể được chỉnh sửa bằng tay. Các tham số và giá trị của chúng có thể được cấu hình lại trong quá trình thực hiện chương trình; để thực hiện việc này, bạn phải viết bộ quy trình của riêng mình để tìm kiếm một tham số trong danh sách và thực hiện các thay đổi đối với giá trị của nó. Ngoài ra còn có một cách dễ dàng hơn: bạn có thể sao chép chuỗi vào danh sách chuỗi của Delphi và sử dụng cơ chế cặp tên-giá trị. Kỹ thuật này sẽ được trình bày trong ví dụ JetText, sẽ được thảo luận sau trong phần "Truy cập tệp văn bản qua Jet".
Khi bạn đã tạo chuỗi kết nối, bạn có thể chọn bảng. Mở rộng danh sách các bảng bằng thuộc tính TableName trong cửa sổ Object Inspector. Chọn bảng Khách hàng. Thêm thành phần DataSource và điều khiển DBGrid, sau đó kết nối chúng lại với nhau. Kết quả là một chương trình thực sự, mặc dù nguyên thủy, sử dụng ADO (đầy đủ nguồnđược định dạng làm ví dụ FirstAdoExample). Để xem dữ liệu, hãy đặt thuộc tính Hoạt động của tập dữ liệu thành True hoặc mở tập dữ liệu bên trong trình xử lý sự kiện FormCreate (như được thực hiện trong ví dụ). Phương pháp thứ hai tránh được các vấn đề nếu cơ sở dữ liệu không có sẵn ở giai đoạn thiết kế.

Nếu bạn định sử dụng dbGo làm công nghệ truy cập cơ sở dữ liệu chính của mình, bạn có thể muốn di chuyển thành phần DataSource sang trang ADO của Bảng thành phần để không phải liên tục chuyển từ trang này sang trang khác. Nếu bạn sử dụng ADO kết hợp với công nghệ khác, bạn có thể mô phỏng thiết lập DataSource trên nhiều trang. Để thực hiện việc này, bạn cần tạo Mẫu thành phần cho thành phần DataSource và đặt nó trên trang ADO.

Thành phần kết nối ADO

Khi bạn sử dụng thành phần ADOTable, nó sẽ tạo thành phần kết nối cơ sở dữ liệu riêng phía sau bạn. Tuy nhiên, bạn không bắt buộc phải sử dụng kết nối cụ thể này. Nói chung, bạn nên tạo kết nối của riêng mình bằng cách sử dụng thành phần ADOConnection, về cơ bản tương đương với thành phần dbExpress SQLConnection và thành phần Cơ sở dữ liệu BDE. Thành phần ADOConnection cho phép bạn định cấu hình đúng quy trình xác thực, kiểm soát các giao dịch, thực hiện trực tiếp các lệnh gửi đến cơ sở dữ liệu và nó cũng cho phép bạn giảm số lượng kết nối tồn tại trong ứng dụng.
Sử dụng ADOConnection khá đơn giản. Đặt thành phần này vào biểu mẫu và đặt thuộc tính ConnectionString của nó giống như cách bạn đã làm với thành phần ADOTable. Ngoài ra, bạn có thể nhấp đúp vào thành phần ADOConnection (hoặc chọn Trình chỉnh sửa thành phần từ menu ngữ cảnh) để truy cập trực tiếp vào trình chỉnh sửa chuỗi kết nối. Nếu chuỗi kết nối (ConnectionString) trỏ đến cơ sở dữ liệu bạn cần, bạn có thể tắt hộp thoại kết nối cơ sở dữ liệu bằng cách đặt thuộc tính loginPrompt thành Sai. Để sử dụng kết nối mới trong ví dụ trước, hãy đặt giá trị ADOConnection1 thành thuộc tính Connection của thành phần ADOTable1. Bạn sẽ thấy giá trị thuộc tính ConnectionString trở nên trống vì thuộc tính Connection và ConnectionString loại trừ lẫn nhau. Ưu điểm của việc sử dụng ADOConnection là chuỗi kết nối hiện được lưu trữ ở một nơi, thay vì được lưu trữ ở nhiều thành phần khác nhau. Một ưu điểm quan trọng khác là một số thành phần khác nhau có thể chia sẻ cùng một kết nối với máy chủ cơ sở dữ liệu. Trừ khi bạn thêm thành phần ADOConnection vào chương trình của mình theo cách thủ công, mỗi thành phần ADO sẽ có kết nối riêng với máy chủ.

Tệp liên kết dữ liệu

Vì vậy, thành phần ADOConnection cho phép bạn tập trung định nghĩa chuỗi kết nối trong một biểu mẫu hoặc mô-đun dữ liệu. Tuy nhiên, cách tiếp cận này vẫn có một nhược điểm lớn: nếu bạn xác định cơ sở dữ liệu bằng tên tệp, đường dẫn đến cơ sở dữ liệu đó sẽ được mã hóa cứng bên trong tệp thực thi của ứng dụng. Kết quả là khả năng của ứng dụng sẽ bị hạn chế đáng kể. Để giải quyết vấn đề này, ADO sử dụng cái được gọi là Tệp liên kết dữ liệu. Tệp liên kết dữ liệu là một chuỗi kết nối được định dạng dưới dạng tệp INI. Ví dụ: Delphi cài đặt tệp dbdems.udl, chứa văn bản sau:

Tệp liên kết dữ liệu có thể có bất kỳ phần mở rộng nào, nhưng nên sử dụng phần mở rộng .UDL. Bạn có thể tạo một tập tin như vậy bằng cách sử dụng bất kỳ soạn thảo văn bản. Ngoài ra, để tạo một tập tin như vậy, bạn có thể mở một cửa sổ Windows Explorer, nhấp chuột phải vào một trong các thư mục trên đĩa, chọn Mới > Tài liệu văn bản, thay đổi phần mở rộng tệp thành .UDL (Tôi giả sử rằng trên hệ thống Explorer của bạn hiển thị phần mở rộng tệp), sau đó nhấp đúp vào tệp - Cái này sẽ khởi chạy Trình soạn thảo chuỗi kết nối của Microsoft.
Nếu bạn chọn Sử dụng tệp liên kết dữ liệu trong trình chỉnh sửa thuộc tính ConnectionString, thuộc tính sẽ tự động có chuỗi "FILE NAME =" theo sau là tên của tệp liên kết dữ liệu. Kỹ thuật này được thể hiện trong ví dụ DataLinkFile. Các tệp liên kết dữ liệu có thể được đặt ở bất kỳ đâu trên đĩa, nhưng ADO sử dụng một thư mục tiêu chuẩn để lưu trữ các tệp này. Bạn có thể tìm ra tên của thư mục này bằng hàm DataLinkDir, được xác định trong mô-đun ADODB. Nếu cấu hình là mặc định trong MDAC thì hàm này sẽ trả về như sau:

C:\Tệp chương trình\Tệp chung\System\OLE DB\Liên kết dữ liệu

Thuộc tính động

Hãy tưởng tượng rằng bạn đang phát triển một tầng trung gian nằm giữa các máy khách và một số cơ sở dữ liệu. Một mặt, bạn phải tạo một giao diện lập trình thống nhất duy nhất để truy cập vào một số cơ sở dữ liệu khác nhau, mặt khác, giao diện này phải cung cấp quyền truy cập vào các khả năng cụ thể của từng cơ sở dữ liệu. Để giải quyết cả hai vấn đề này, bạn có thể thiết kế một giao diện nặng là tổng hợp các khả năng của tất cả các cơ sở dữ liệu mà nó được thiết kế để tương tác. Mỗi lớp của giao diện như vậy phải bao gồm tất cả các thuộc tính và phương thức có thể có, nhưng chỉ một tập hợp con các thuộc tính và phương thức của lớp có thể được sử dụng để làm việc với một cơ sở dữ liệu cụ thể. Tôi hy vọng không cần phải chứng minh cho bạn thấy rằng giải pháp này không phải là giải pháp tốt nhất. Để giải quyết vấn đề này, ADO sử dụng các thuộc tính động. Trên thực tế, tất cả các giao diện ADO, cũng như các thành phần dbGo tương ứng của chúng, đều có một thuộc tính được gọi là Thuộc tính. Thuộc tính này là tập hợp các thuộc tính cụ thể cho cơ sở dữ liệu hiện tại. Các thuộc tính này có thể được truy cập bằng cách chỉ định số chỉ mục của chúng, ví dụ:

ShowMessage(ADOTable1.Properties.Value);

Tuy nhiên, trong hầu hết các trường hợp, sẽ thuận tiện hơn khi sử dụng tên: ShowMessage(ADOConnection1.Properties["DBMS Name"].Value); Tập hợp các thuộc tính động được xác định bởi loại đối tượng và nhà cung cấp OLE DB. Để giúp bạn hiểu được tầm quan trọng của các thuộc tính động, tôi sẽ lưu ý rằng các thành phần như ADOConnection hoặc Recordset hỗ trợ khoảng 100 thuộc tính động. Như bạn sẽ thấy trong chương này, các thuộc tính động được sử dụng rộng rãi trong ADO để giải quyết nhiều vấn đề khác nhau.

Một sự kiện quan trọng liên quan đến việc sử dụng thuộc tính động là sự kiện OnRecordsetCreate. Sự kiện này lần đầu tiên xuất hiện trong Delphi 6. Sự kiện OnRecordsetCreate được kích hoạt ngay sau khi Recordset được tạo nhưng trước khi thành phần được mở. Sự kiện này rất hữu ích cho việc thiết lập các thuộc tính động mà chỉ có thể được thiết lập khi Recordset ở trạng thái đóng.

Lấy thông tin lược đồ

ADO sử dụng phương thức OpenSchema của thành phần ADOConnection để lấy thông tin lược đồ. Phương thức này có bốn tham số:

    Loại dữ liệu sẽ được trả về bằng phương thức OpenSchema. Giá trị này thuộc loại TSchemaInfo: một tập hợp gồm 40 giá trị, bao gồm danh sách các bảng, chỉ mục, cột, dạng xem và các thủ tục được lưu trữ.

    Một bộ lọc phải được áp dụng cho dữ liệu trước khi nó được trả về. Một ví dụ về tham số này sẽ được trình bày sau.

    GUID cho yêu cầu dành riêng cho nhà cung cấp. Tham số này chỉ được sử dụng nếu tham số đầu tiên bằng giá trị của siProviderSpecific.

    Thành phần ADODataSet trong đó dữ liệu sẽ được trả về. Tùy chọn này minh họa một chủ đề phổ biến trong ADO: nếu một phương thức trả về một số dữ liệu, nó sẽ ghi dữ liệu đó vào Tập bản ghi hoặc theo thuật ngữ Delphi, thành phần ADODataSet.

Để sử dụng phương thức OpenSchema, bạn phải mở ADOConnection. Đoạn mã sau, là một phần của ví dụ OpenSchema, truy xuất danh sách các khóa chính cho mỗi bảng và điền chúng vào thành phần ADODataSet:

ADOConnection1.OpenSchema(siPrimaryKeys, EmptyParam, EmptyParam, ADODataSet1);

Mỗi trường trong khóa chính tương ứng với một hàng trong tập dữ liệu kết quả. Như vậy, nếu một bảng có khóa chính gồm hai trường thì sẽ có hai hàng tương ứng với bảng này trong tập dữ liệu thu được. Giá trị EmptyParam cho biết tham số được gán một giá trị trống, có nghĩa là tham số đó bị bỏ qua. Kết quả của mã được hiển thị trong Hình. 15.3.


Nếu bạn chuyển EmptyParam làm tham số thứ hai, tập dữ liệu kết quả sẽ bao gồm tất cả thông tin thuộc loại được chỉ định cho toàn bộ cơ sở dữ liệu. Rất thường xuyên, để thuận tiện, bạn muốn lọc thông tin. Tất nhiên, bạn có thể áp dụng bộ lọc Delphi truyền thống cho tập dữ liệu kết quả cho mục đích này (bạn có thể sử dụng thuộc tính Filter và Filtered hoặc sự kiện OnFilterRecord cho việc này). Tuy nhiên, trong trường hợp này, việc lọc sẽ được thực hiện ở phía máy khách. Tham số thứ hai cho phép bạn lọc hiệu quả hơn ở phía nguồn của thông tin lược đồ. Một bộ lọc được định nghĩa là một mảng các giá trị. Mỗi phần tử mảng có một ý nghĩa đặc biệt liên quan đến kiểu dữ liệu được trả về. Ví dụ: mảng bộ lọc khóa chính bao gồm ba phần tử: thư mục (nghĩa là cơ sở dữ liệu), lược đồ và tên bảng. Ví dụ này trả về danh sách các khóa chính trong bảng Khách hàng:

var Bộ lọc: OLEVariant; bắt đầu Bộ lọc:= VarArrayCreate(, varVariant); Lọc := "KHÁCH HÀNG"; ADOConnection1.OpenSchema(siPrimaryKeys, Filter, EmptyParam, ADODataSet1); kết thúc;

GHI CHÚ

Thông tin tương tự có thể được lấy bằng ADOX. ADOX là công nghệ ADO bổ sung cho phép bạn truy xuất và sửa đổi thông tin lược đồ. Trong SQL, tương đương với ADOX là DDL (Ngôn ngữ định nghĩa dữ liệu), nghĩa là các câu lệnh CREATE, ALTER, DROP và DCL (Ngôn ngữ điều khiển dữ liệu), tức là các câu lệnh GRANT, REVOKE. dbGo không hỗ trợ trực tiếp công nghệ ADOX, nhưng bạn có thể nhập thư viện kiểu ADOX và sử dụng nó trong các ứng dụng Delphi. Không giống như phương pháp OpenSchema, việc triển khai ADOX của Delphi không phổ biến nên không phải lúc nào cũng thuận tiện khi sử dụng. Nếu bạn chỉ muốn lấy thông tin lược đồ nhưng không thay đổi nó, thì sử dụng phương pháp OpenSchema cho mục đích này thường sẽ thuận tiện hơn.

Sử dụng động cơ phản lực

Bây giờ bạn đã hiểu cơ bản về MDAC và ADO, chúng ta có thể chuyển sang Động cơ phản lực. Đối với một số người, cơ chế này được quan tâm, đối với những người khác thì nó hoàn toàn không cần thiết. Nếu bạn làm việc với Access, Paradox, dBase, Excel, Lotus 1-2-3, HTML hoặc dữ liệu được lưu trữ trong tệp văn bản thì tài liệu được đề cập ở đây sẽ hữu ích cho bạn. Nếu bạn không quan tâm đến các định dạng được liệt kê ở đây, bạn có thể bỏ qua toàn bộ phần này.
Thông thường, Jet được liên kết với cơ sở dữ liệu Microsoft Access. Thật vậy, Access là hệ thống chính mà Jet tương tác. Tuy nhiên, ngoài Access, Jet cho phép bạn làm việc với nhiều nguồn dữ liệu cục bộ khác. Nhiều người không biết điều này nhưng đây là một trong những ưu điểm chính của Jet. Tương tác với Access thông qua Jet tương đối đơn giản ở chế độ hoạt động tiêu chuẩn của nó, vì vậy chúng tôi sẽ không đề cập đến chế độ sử dụng Jet đó ở đây. Thay vào đó, chúng ta sẽ xem xét kỹ hơn cách Jet tương tác với các định dạng khác.

GHI CHÚ

Động cơ phản lực được bao gồm trong một số phiên bản (nhưng không phải tất cả) của MDAC. Đặc biệt, nó bị thiếu trong phiên bản 2.6. Đã có lúc, có rất nhiều tranh cãi về việc liệu các lập trình viên sử dụng các công cụ phát triển không phải của Microsoft có thể đưa động cơ phản lực vào các sản phẩm phần mềm của họ hay không. Người ta chính thức tin rằng điều này là có thể. Jet có thể được tải xuống miễn phí từ trang web của Microsoft và được bao gồm trong nhiều sản phẩm của Microsoft.

Có hai nhà cung cấp OLE DB cho động cơ phản lực: Jet 3.51 OLE DB và Jet 4.0 OLE DB. Nhà cung cấp Jet 3.51 OLE DB sử dụng Jet 3.51 và chỉ hỗ trợ Access 97. Nếu bạn chỉ sử dụng Access 97 và không chuyển sang Access 2000, Jet 3.51 thường sẽ cung cấp hiệu suất tốt hơn Nhà cung cấp Jet 4.0 OLE DB.
Nhà cung cấp Jet 4.0 OLE DB hỗ trợ trình điều khiển Access 97, Access 2000 và IISAM (Phương pháp truy cập tuần tự được lập chỉ mục có thể cài đặt). Trình điều khiển ISAM đã cài đặt được viết riêng cho Jet Engine và cung cấp quyền truy cập vào các định dạng như Paradox, dBase và tệp văn bản. Chính khả năng sử dụng các trình điều khiển này đã khiến Jet trở thành một công cụ hữu ích và tiện lợi. Danh sách đầy đủ các trình điều khiển ISAM được cài đặt trên máy tính của bạn được xác định bởi bộ phần mềm được cài đặt trên hệ thống. Danh sách này nằm trong sổ đăng ký tại:

Định dạng HKEY_LOCAL_MACHINE\Software\Microsoft\Jet\4.0\ISAM

Jet cung cấp trình điều khiển cho Paradox, dBase, Excel, tệp văn bản và HTML.

Nhập khẩu và xuất khẩu

Động cơ phản lực thuận tiện sử dụng cho việc nhập và xuất dữ liệu. Quá trình xuất dữ liệu giống nhau đối với từng định dạng được xuất và bao gồm việc thực thi câu lệnh SELECT ở định dạng cụ thể. Hãy xem ví dụ về xuất dữ liệu từ cơ sở dữ liệu Access trong ví dụ DBDemos sang bảng Paradox. Để thực hiện việc này, hãy thêm ADOConnection đang hoạt động có tên ADOConnection1 vào chương trình JetImportExport. Kết nối này sử dụng động cơ phản lực để mở cơ sở dữ liệu. Đoạn mã sau xuất bảng Khách hàng sang tệp định dạng Nghịch lý Customer.db:

CHỌN * VÀO Khách hàng TRONG "C:\tmp" "Paradox 7.x;" TỪ KHÁCH HÀNG

Chúng ta hãy xem các thành phần của biểu thức SQL này. Từ khóa INTO chỉ định bảng mới sẽ được tạo nhờ câu lệnh SELECT. Trước khi thực thi mã này, bảng có tên này không được tồn tại trong cơ sở dữ liệu. Từ khóa IN chỉ định cơ sở dữ liệu mà bảng mới đang được thêm vào. Trong Paradox, đây phải là thư mục đã tồn tại trên đĩa. Ngay sau tên cơ sở dữ liệu là tên của trình điều khiển IISAM sẽ được sử dụng để xuất dữ liệu. Bạn phải thêm dấu chấm phẩy (;) vào cuối tên trình điều khiển. Từ khóa FROM là thành phần tiêu chuẩn của bất kỳ biểu thức SELECT nào. Trong ví dụ đang xem xét, thao tác này được thực hiện bằng cách sử dụng thành phần ADOConnection1; thay vì tên thư mục cố định, thư mục chương trình hiện tại sẽ được sử dụng:

Mới tập tin Excel với tên dbdemos.xls được tạo trong thư mục chương trình hiện tại. Tài liệu Excel này thêm một sổ làm việc có tên Khách hàng chứa tất cả dữ liệu từ bảng Khách hàng trong cơ sở dữ liệu Access có tên dbdemo. mdb.
Đây là một biểu thức khác xuất cùng một dữ liệu sang tệp HTML:

ADOConnection1.Execute("CHỌN * VÀO VÀO "" + CurrentFolder + "" "Xuất HTML;" TỪ KHÁCH HÀNG");

Trong trường hợp này, cơ sở dữ liệu là một thư mục (như trong Paradox). Tên bảng bao gồm phần mở rộng .htm nên tên bảng phải được đặt trong dấu ngoặc vuông. Xin lưu ý rằng trình điều khiển IISAM không chỉ được gọi là HTML mà còn là Xuất HTML. Đúng như tên gọi, trình điều khiển chỉ cho phép bạn xuất dữ liệu chứ không cho phép bạn nhập dữ liệu.
Cuối cùng, chúng ta hãy xem trình điều khiển Nhập HTML của Jet, đây là một bổ sung hữu ích cho Xuất HTML. Thêm thành phần ADOTable vào biểu mẫu. Định cấu hình ConnectionString để sử dụng nhà cung cấp Jet 4.0 OLE DB. Đặt tham số Thuộc tính mở rộng của chuỗi kết nối thành Nhập HTML. Đối với tên cơ sở dữ liệu, hãy chỉ định tên của tệp HTML đã được tạo do xuất (sớm hơn một chút), chính xác hơn là Customer.htm. Bây giờ hãy đặt thuộc tính TableName thành Khách hàng. Mở bảng tính của bạn - bạn vừa nhập dữ liệu từ tệp HTML. Xin lưu ý rằng nếu bạn cố cập nhật dữ liệu, hệ thống sẽ báo lỗi vì trình điều khiển chỉ được nhập. Nếu bạn đã tạo tệp HTML của riêng mình có chứa các bảng và muốn mở các bảng đó bằng trình điều khiển này, bạn phải nhớ rằng tên bảng là giá trị của thẻ chú thích trong phần bảng HTML.

Làm việc với con trỏ

Mỗi bộ dữ liệu của ADO có hai thuộc tính song hành với nhau và có tác động đáng kể đến ứng dụng của bạn. Đây là các thuộc tính CursorLocation và CursorType. Nếu bạn muốn hiểu cách hoạt động của tập dữ liệu ADO, bạn phải tìm hiểu hai thuộc tính này.

Vị trí con trỏ (thuộc tính CursorLocation)

Thuộc tính CursorLocation xác định cách truy xuất và sửa đổi dữ liệu. Thuộc tính này có thể được đặt thành một trong hai giá trị: clUseClient (con trỏ phía máy khách) hoặc clUseServer (con trỏ phía máy chủ). Việc lựa chọn giá trị ảnh hưởng lớn đến chức năng, hiệu suất và khả năng mở rộng của cơ sở dữ liệu.
Con trỏ máy khách được phục vụ bởi Công cụ con trỏ ADO. Công cụ này là một ví dụ tuyệt vời về nhà cung cấp dịch vụ OLE DB: nó cung cấp dịch vụ cho các nhà cung cấp OLDE DB khác. Công cụ con trỏ ADO quản lý việc xử lý dữ liệu phía máy khách. Khi bạn mở một tập dữ liệu, tất cả dữ liệu trong tập kết quả sẽ được tải xuống từ máy chủ về máy khách. Sau đó, dữ liệu được lưu trữ trong bộ nhớ, được cập nhật và xử lý bằng Công cụ con trỏ ADO. Cách tiếp cận này tương tự như việc sử dụng ClientDataSet trong các ứng dụng dbExpress. Ưu điểm là sau khi truyền dữ liệu sang phía máy khách, mọi thao tác với dữ liệu này sẽ được thực hiện nhanh hơn nhiều. Ngoài ra, do các thao tác được thực hiện trong bộ nhớ nên Công cụ con trỏ ADO mạnh hơn bất kỳ con trỏ phía máy chủ nào. Tiếp theo, tôi sẽ xem xét kỹ hơn những lợi ích này, cũng như các công nghệ khác dựa trên con trỏ máy khách (cụ thể là các tập bản ghi bị vô hiệu hóa và liên tục). Con trỏ phía máy chủ được quản lý bởi chính RDBMS. Trong kiến ​​trúc máy khách/máy chủ dựa trên các sản phẩm như SQL Server, Oracle hoặc InterBase, điều này có nghĩa là con trỏ được điều khiển trên máy chủ từ xa. Trong trường hợp cơ sở dữ liệu trên máy tính để bàn như Access hoặc Paradox, con trỏ máy chủ được điều khiển bởi sản phẩm phần mềm phục vụ cơ sở dữ liệu. Nghĩa là, về mặt logic, con trỏ nằm trên “máy chủ”, nhưng về mặt vật lý, cơ sở dữ liệu cùng với con trỏ nằm trên máy khách. Nói chung, con trỏ phía máy chủ tải nhanh hơn con trỏ phía máy khách vì khi bạn mở tập dữ liệu bằng con trỏ phía máy chủ, không cần phải di chuyển tất cả dữ liệu sang phía máy khách. Điều này làm cho con trỏ máy chủ phù hợp hơn để phục vụ bộ lớn dữ liệu, nghĩa là khi máy khách không có đủ bộ nhớ để lưu trữ toàn bộ tập dữ liệu. Để hiểu khả năng của cả hai loại con trỏ, tốt nhất bạn nên xem cách chúng hoạt động trong một tình huống nhất định. Ví dụ: bạn có thể lấy tình huống chặn hồ sơ. Tôi sẽ nói nhiều hơn về việc chặn sau. (Nếu bạn muốn khóa một bản ghi, bạn sẽ cần một con trỏ máy chủ vì RDBMS cần biết rằng bản ghi đó đã bị khóa.)
Một tính năng khác cần xem xét khi chọn vị trí con trỏ là khả năng mở rộng. Con trỏ máy chủ được đặt ở phía máy chủ. Càng nhiều người dùng kết nối với cơ sở dữ liệu, nhiều con trỏ hơnđược tạo trên máy chủ. Với mỗi con trỏ mới, tải trên máy chủ sẽ tăng lên. Do đó, khi số lượng người dùng tăng lên, hiệu suất tổng thể của hệ thống có thể giảm đáng kể. Bằng cách sử dụng con trỏ phía máy khách, bạn có thể tăng đáng kể khả năng mở rộng ứng dụng của mình. Việc mở con trỏ máy khách sẽ khiến bạn tốn nhiều chi phí hơn, vì trong quá trình mở, tất cả dữ liệu sẽ được chuyển sang phía máy khách, nhưng việc duy trì con trỏ máy khách sẽ ít gây gánh nặng hơn cho máy chủ vì tải chính liên quan đến việc này được đặt trên máy khách.

Loại con trỏ (thuộc tính CursorType)

Loại con trỏ phần lớn được xác định bởi vị trí của con trỏ. Có năm loại con trỏ, một trong số đó không được sử dụng. Một loại không được sử dụng được gọi là không xác định. Có nhiều giá trị trong ADO tương ứng với một giá trị không xác định. Ở Delphi những giá trị này thực sự không bao giờ được sử dụng. Những giá trị này chỉ hiện diện ở Delphi vì chúng hiện diện trong ADO. Thực tế là công nghệ ADO ban đầu được phát triển cho các ngôn ngữ như Visual Basic và C. Trong các ngôn ngữ này, bạn làm việc trực tiếp với các đối tượng mà không cần sự hỗ trợ của các cơ chế phụ trợ như dbGo. Kết quả là bạn có thể tạo một tập bản ghi mở (theo thuật ngữ ADO là tập bản ghi) mà không cần chỉ định giá trị cho từng thuộc tính. Như vậy, giá trị của một số thuộc tính sẽ không được xác định. Trong trường hợp này, thuộc tính được đặt thành không xác định. Tuy nhiên, trong dbGo bạn đang xử lý các thành phần. Các thành phần có hàm tạo. Hàm tạo là một hàm bắt buộc khởi tạo từng thuộc tính của thành phần. Khi bạn tạo một thành phần dbGo, mỗi thuộc tính của nó có một giá trị cụ thể. Do đó, không cần sử dụng giá trị không xác định (không được chỉ định).
Loại con trỏ ảnh hưởng đến cách đọc và cập nhật dữ liệu. Bạn có thể sử dụng một trong bốn loại con trỏ: Chỉ chuyển tiếp, Tĩnh, Bộ khóa và Động. Trước khi chúng ta thảo luận về các kết hợp khác nhau của loại con trỏ và vị trí, có một điều quan trọng cần lưu ý: đối với con trỏ phía máy khách, bạn chỉ có thể sử dụng một loại: con trỏ tĩnh. Tất cả các loại con trỏ khác chỉ có thể được sử dụng ở phía máy chủ. Chúng ta hãy xem xét kỹ hơn các loại con trỏ theo thứ tự tăng chi phí liên quan đến việc bảo trì chúng.

    Chỉ chuyển tiếp (chỉ chuyển tiếp). Loại con trỏ này ít tốn kém nhất về mặt chi phí. Nói cách khác, những con trỏ như vậy mang lại hiệu suất cao nhất. Đúng như tên gọi, con trỏ Chỉ chuyển tiếp cho phép bạn di chuyển qua một tập hợp dữ liệu theo hướng từ đầu đến cuối. Con trỏ đọc từ máy chủ số lượng bản ghi được chỉ định trong thuộc tính CacheSize (mặc định 1), mỗi lần nó rời khỏi bản ghi cuối cùng trong bộ đệm cục bộ, nó sẽ đọc lô bản ghi tiếp theo từ máy chủ. Bất kỳ nỗ lực nào để di chuyển về phía đầu của tập bản ghi bên ngoài bộ đệm cục bộ đều dẫn đến lỗi. Hành vi này tương tự như hành vi của tập dữ liệu trong thư viện dbExpress. Con trỏ Forwardonly không phù hợp lắm để tạo giao diện người dùng trong đó người dùng có quyền kiểm soát hướng di chuyển. Tuy nhiên, một con trỏ như vậy khá phù hợp để thực hiện các thao tác hàng loạt, tạo báo cáo khi xây dựng các ứng dụng web không trạng thái - trong bất kỳ tình huống nào, bạn bắt đầu từ đầu tập dữ liệu và di chuyển về cuối tập dữ liệu. Khi đạt đến điểm cuối, tập dữ liệu sẽ bị đóng.

    Tĩnh (tĩnh). Khi sử dụng con trỏ tĩnh, tập dữ liệu sẽ được di chuyển hoàn toàn sang phía máy khách và được truy cập bằng cửa sổ có kích thước CacheSize. Kết quả là người dùng có thể điều hướng qua tập dữ liệu theo cả hai hướng. Điểm bất lợi là dữ liệu ở dạng tĩnh - các cập nhật, bổ sung và xóa bản ghi do người dùng khác thực hiện không hiển thị với con trỏ tĩnh vì dữ liệu con trỏ đã được đọc.

    Keyset (bộ chìa khóa). Để hiểu cách hoạt động của con trỏ này, hãy chia từ Keyset thành hai phần: key và set. Khóa là khóa, nghĩa là, trong ngữ cảnh này, là mã định danh bản ghi. Thông thường điều này đề cập đến khóa chính. Set là một bộ hoặc một bộ sưu tập. Hóa ra đó là một “bộ chìa khóa”. Khi bạn mở tập dữ liệu từ máy chủ, danh sách đầy đủ tất cả các khóa sẽ được đọc. Ví dụ: nếu một tập dữ liệu được tạo bằng biểu thức CHỌN * TỪ KHÁCH HÀNG thì có thể tạo danh sách các khóa bằng biểu thức CHỌN CUSTID TỪ KHÁCH HÀNG. Bộ khóa được lưu trữ ở phía máy khách cho đến khi đóng con trỏ. Khi một ứng dụng cần dữ liệu, nhà cung cấp OLE DB sẽ đọc các hàng của bảng bằng cách sử dụng bộ khóa hiện có cho mục đích này. Kết quả là, khách hàng luôn xử lý dữ liệu cập nhật. Tuy nhiên, một bộ khóa là tĩnh theo nghĩa là khi con trỏ được mở, các khóa mới không thể được thêm vào bộ đó cũng như không thể xóa các phím khỏi bộ đó. Nói cách khác, nếu người dùng khác thêm bản ghi mới vào bảng, những thay đổi đó sẽ không hiển thị với khách hàng. Các bản ghi đã xóa sẽ không thể truy cập được và mọi thay đổi đối với khóa chính (nói chung, người dùng bị cấm thay đổi khóa chính) cũng không thể truy cập được.

    Năng động. Đây là con trỏ đắt nhất. Con trỏ động hoạt động gần giống như con trỏ bộ phím. Điểm khác biệt là bộ khóa được đọc lại từ máy chủ mỗi khi ứng dụng cần dữ liệu không có trong bộ đệm. Vì giá trị mặc định của thuộc tính ADODataSet.CacheSize là 1 nên các yêu cầu đọc dữ liệu xảy ra khá thường xuyên. Bạn có thể tưởng tượng tải bổ sung mà con trỏ này đặt trên máy chủ DBMS và mạng. Tuy nhiên, khi sử dụng con trỏ này, máy khách không chỉ nhận biết được những thay đổi dữ liệu mà còn biết cả những thao tác thêm và xóa do các máy khách khác thực hiện.

Không phải lúc nào bạn cũng nhận được thứ bạn yêu cầu

Bây giờ bạn đã biết về các loại và vị trí con trỏ, tôi nên cảnh báo bạn rằng không phải tất cả các kết hợp loại và vị trí con trỏ đều được phép. Thông thường, giới hạn này liên quan đến loại RDBMS và/hoặc nhà cung cấp OLE DB. Ví dụ: nếu con trỏ nằm ở phía máy khách thì loại con trỏ chỉ có thể ở dạng tĩnh. Bạn có thể tự quan sát hành vi này. Thêm thành phần ADODataSet vào biểu mẫu, đặt cấu hình thuộc tính ConnectionString để kết nối với bất kỳ cơ sở dữ liệu nào, sau đó đặt thuộc tính ClientLocation thành clUseCursor và thuộc tính CursorType thành ctDynamic. Bây giờ thay đổi giá trị của thuộc tính Active thành True và quan sát thuộc tính CursorType. Giá trị của thuộc tính này sẽ ngay lập tức thay đổi thành ctStatic. Nên làm kết luận quan trọng: Không phải lúc nào bạn cũng nhận được chính xác những gì bạn yêu cầu. Khi bạn mở tập dữ liệu, hãy luôn kiểm tra các giá trị thuộc tính - một số giá trị trong số chúng có thể tự động thay đổi giá trị. Các nhà cung cấp OLE DB khác nhau có những thay đổi về thuộc tính khác nhau. Hãy để tôi đưa ra một vài ví dụ:

    Nhà cung cấp Jet 4.0 OLE DB thay đổi hầu hết các loại con trỏ thành Keyset;

    Nhà cung cấp SQL Server OLE DB thường thay đổi Keyset và Static thành Dynamic;

    Nhà cung cấp Oracle OLE DB thay đổi tất cả các loại con trỏ thành Chỉ chuyển tiếp;

    Nhà cung cấp ODBC OLE DB có thể thực hiện nhiều thay đổi về loại con trỏ tùy thuộc vào trình điều khiển ODBC được sử dụng.

Không có quầy

Khi bạn cố đọc thuộc tính RecordCount của một số tập dữ liệu ADO, đôi khi bạn thấy rằng thuộc tính đó bằng -1. Con trỏ Forwardonly không biết có bao nhiêu bản ghi trong tập dữ liệu cho đến khi nó đến cuối tập hợp. Vì lý do này, thuộc tính RecordCount bằng giá trị - 1. Con trỏ tĩnh luôn biết có bao nhiêu bản ghi trong tập dữ liệu, vì con trỏ tĩnh đọc tất cả dữ liệu trong tập hợp tại thời điểm nó được mở. Con trỏ Keyset cũng biết số lượng bản ghi trong tập hợp vì nó truy xuất một tập hợp giá trị khóa cố định từ cơ sở dữ liệu khi tập dữ liệu được mở. Vì vậy, đối với con trỏ Tĩnh và Bộ khóa, bạn có thể truy cập thuộc tính RecordCount và lấy số lượng bản ghi chính xác trong tập hợp. Con trỏ động không thể biết số lượng bản ghi một cách đáng tin cậy vì mỗi lần đọc dữ liệu, nó sẽ đọc lại bộ khóa, do đó thuộc tính RecordCount cho con trỏ này luôn bằng -1. Bạn có thể tránh hoàn toàn việc sử dụng thuộc tính RecordCount và thay vào đó hãy sử dụng câu lệnh SELECT COUNT(*) FROM table_name. Tuy nhiên, kết quả là bạn sẽ nhận được giá trị không chính xác về số lượng bản ghi trong bảng cơ sở dữ liệu - giá trị này không phải lúc nào cũng trùng với số lượng bản ghi trong tập dữ liệu.

Chỉ số khách hàng

Một trong những lợi ích của con trỏ phía máy khách là khả năng tạo các chỉ mục cục bộ hoặc phía máy khách. Hãy tưởng tượng rằng bạn có một tập dữ liệu ADO với một con trỏ máy khách và tập hợp này được nối với bảng Khách hàng từ ví dụ DBDemos. Hãy tưởng tượng rằng một DBGrid được kết nối với bộ này. Đặt thuộc tính IndexFieldNames thành CompanyName. Lưới sẽ ngay lập tức hiển thị các bản ghi, sắp xếp chúng theo giá trị của trường CompanyName. Điều quan trọng cần lưu ý là ADO không đọc lại dữ liệu từ nguồn để xây dựng chỉ mục. Chỉ mục được hình thành dựa trên dữ liệu được lưu trữ trong bộ nhớ. Nhờ đó, thứ nhất, chỉ mục được hình thành khá nhanh và thứ hai, không có tải bổ sung nào được tạo ra trên mạng và DBMS. Nếu không, cùng một dữ liệu sẽ phải được truyền đi truyền lại qua mạng theo một thứ tự sắp xếp khác.
Thuộc tính IndexFieldNames có một số tính năng thú vị khác. Ví dụ: đặt thuộc tính này thành Country;CompanyName - bạn sẽ thấy rằng các bản ghi được sắp xếp trước tiên theo tên quốc gia và sau đó theo tên công ty. Bây giờ, hãy đặt thuộc tính IndexField-Names thành CompanyName DESC (từ khóa DESC phải bằng chữ in hoa, không phải desc hoặc Desc). Kết quả là các bản ghi sẽ được sắp xếp theo thứ tự giá trị giảm dần.
Tính năng đơn giản nhưng mạnh mẽ này cho phép bạn giải quyết một trong những vấn đề cấp bách nhất liên quan đến lập trình cơ sở dữ liệu. Người dùng thích hỏi các lập trình viên một câu hỏi không thể tránh khỏi và gây bực bội nhưng hoàn toàn chính đáng: “Tôi có thể nhấp vào tiêu đề cột lưới để sắp xếp dữ liệu của mình không?” Có một số cách để giải quyết vấn đề này. Ví dụ: bạn có thể sử dụng điều khiển tiêu chuẩn (không nhận biết dữ liệu), chẳng hạn như ListView, hỗ trợ cơ chế sắp xếp tích hợp sẵn. Ngoài ra, bạn có thể xử lý sự kiện OnTitleClick của thành phần DBGrid và trong trình xử lý, thực thi lại câu lệnh SQL SELECT, thêm vào nó đội phù hợpĐẶT BỞI. Tuy nhiên, bất kỳ giải pháp nào trong số này không thể được gọi là hoàn toàn thỏa đáng. Nếu dữ liệu được lưu trữ ở phía máy khách (chúng ta đã thảo luận về phương pháp này khi nói về thành phần ClientDataSet), bạn có thể sử dụng một chỉ mục được tạo trong bộ nhớ của máy khách. Thêm trình xử lý sự kiện OnTitleClick sau cho lưới (mã nguồn đầy đủ được bao gồm trong mẫu ClientIndexes):

thủ tục Tfrom1.DBGrid1TitleClick(Cột: Tcột); bắt đầu nếu như ADODataSet1.IndexFieldNames = Cột.Field.FieldName sau đó ADODataSet1.IndexFieldNames:= Cột.Field.FieldName + "DESC" khác ADODataSet1.IndexFieldNames:= Cột.Field.FieldName kết thúc;

Mã đơn giản này kiểm tra xem chỉ mục hiện tại có dựa trên trường tương ứng với cột lưới có tiêu đề được nhấp vào hay không. Nếu có thì một chỉ mục mới sẽ được xây dựng dựa trên cùng một trường nhưng theo thứ tự giảm dần. Nếu không thì một chỉ mục mới sẽ được hình thành dựa trên cột. Khi người dùng nhấp vào tiêu đề cột lần đầu tiên, các mục sẽ được sắp xếp theo thứ tự giá trị tăng dần. Khi người dùng nhấp vào cùng một cột lần thứ hai, các mục sẽ được sắp xếp theo thứ tự giảm dần. Bạn có thể nâng cao trình xử lý này để cho phép người dùng nhấp vào nhiều tiêu đề trong khi giữ phím Ctrl. Trong trường hợp này, các chỉ mục phức tạp hơn có thể được hình thành.

GHI CHÚ

Điều tương tự có thể được thực hiện bằng cách sử dụng thành phần ClientDataSet, nhưng thành phần này không hỗ trợ từ khóa DESC, vì vậy bạn sẽ cần phải viết thêm mã để sắp xếp theo thứ tự giảm dần. Hơn nữa, nếu thứ tự sắp xếp bị thay đổi, thành phần ClientDataSet sẽ xây dựng lại chỉ mục - đây là một thao tác không cần thiết và có thể làm chậm.

Nhân bản

Công nghệ ADO hỗ trợ nhiều tính năng thú vị. Bạn có thể phàn nàn rằng sự phong phú của các tính năng dẫn đến việc tăng kích thước của mã thực thi phải được cài đặt trên máy khách. Tuy nhiên, nhờ khả năng phong phú của ADO, bạn có thể xây dựng các ứng dụng mạnh mẽ và đáng tin cậy. Một trong những tính năng tiện lợi của ADO là khả năng sao chép. Một tập bản ghi nhân bản là bộ mới bản ghi có cùng tập thuộc tính với bản gốc. Đầu tiên, tôi sẽ giải thích quá trình nhân bản diễn ra như thế nào, sau đó tôi sẽ nói về lý do tại sao nó lại cần thiết.

GHI CHÚ

Thành phần ClientDataSet cũng hỗ trợ nhân bản, nhưng tôi chưa đề cập đến tính năng này trong Chương 13.

Để sao chép một tập dữ liệu (trong ADO, một tập bản ghi), hãy sử dụng phương thức Clone. Bạn có thể sao chép bất kỳ tập dữ liệu ADO nào, nhưng trong ví dụ này, chúng tôi sẽ sử dụng thành phần ADOTable. Chương trình DataClone (Hình 15.6) chứa hai thành phần ADOTable - một trong số chúng được kết nối với dữ liệu và thành phần thứ hai trống. Cả hai bộ dữ liệu đều được kết nối với DataSource và lưới. Khi người dùng nhấp vào nút Sao chép bộ dữ liệu, một dòng mã sẽ được thực thi để sao chép tập dữ liệu:

ADOTable2.Clone(ADOTable1);



Dòng này sao chép tập dữ liệu ADOTable1 và đặt bản sao kết quả vào tập dữ liệu ADOTable2. Điều này cung cấp cho bạn hai chế độ xem của cùng một dữ liệu. Mỗi bộ có con trỏ riêng tới bản ghi hiện tại và bản sao thông tin trạng thái riêng của nó, do đó bản sao không ảnh hưởng đến bản sao gốc của dữ liệu. Hành vi này làm cho bản sao trở thành một công cụ tuyệt vời để làm việc với tập dữ liệu mà không ảnh hưởng đến dữ liệu gốc. Một tính năng thú vị khác: bạn có thể tạo một số mục hoạt động khác nhau - bản sao khác nhau các mục hoạt động có thể khác nhau. Loại chức năng này không thể được triển khai ở Delphi chỉ bằng một bộ dữ liệu.

Một tập dữ liệu chỉ có thể được sao chép nếu nó hỗ trợ dấu trang. Vì lý do này, không thể sao chép các con trỏ động và chỉ chuyển tiếp. Để xác định xem tập bản ghi có hỗ trợ dấu trang hay không, bạn có thể sử dụng phương thức Hỗ trợ (ví dụ: ADOTable1.Supports()). Một tác dụng phụ của việc nhân bản là các dấu trang được tạo bởi một trong các bản sao có thể được sử dụng bởi tất cả các bản sao khác.

Xử lý giao dịch

Trong phần “Sử dụng giao dịch” của Chương 14, chúng ta đã thảo luận rằng cơ chế giao dịch cho phép các nhà phát triển nhóm các hoạt động cơ sở dữ liệu riêng lẻ thành một quy trình duy nhất, nhất quán về mặt logic.
Việc xử lý giao dịch trong ADO được thực hiện bằng cách sử dụng thành phần ADOConnection; các phương thức BeginTrans, CommitTrans và RollbackTrans được sử dụng cho việc này. Các phương thức này hoạt động tương tự như các phương thức của dbExpress và BDE. Để nghiên cứu cơ chế giao dịch được tích hợp trong ADO, chúng ta sẽ sử dụng chương trình TransProcessing. Chương trình bao gồm một thành phần ADOConnection, chuỗi kết nối của nó (thuộc tính ConnectionString) được cấu hình để sử dụng nhà cung cấp Jet 4.0 OLE DB và để truy cập vào tệp dbdemos.mdb. Chương trình chứa thành phần ADOTable được kết nối với bảng Khách hàng và được liên kết với các thành phần DataSource và DBGrid để hiển thị dữ liệu. Cuối cùng, chương trình chứa ba nút được thiết kế để thực hiện các lệnh sau:

ADOConnection1.BeginTrans; ADOConnection1.CommitTrans; ADOConnection1.RollbackTrans;


Sử dụng chương trình này, bạn có thể thực hiện các thay đổi đối với cơ sở dữ liệu và sau đó khôi phục giao dịch, nghĩa là hoàn tác những thay đổi đó. Điều này sẽ khôi phục cơ sở dữ liệu về trạng thái trước khi giao dịch bắt đầu. Cần lưu ý rằng việc xử lý giao dịch được thực hiện khác nhau tùy thuộc vào cơ sở dữ liệu và nhà cung cấp OLE DB. Ví dụ: nếu bạn kết nối với Paradox bằng nhà cung cấp ODBC OLE DB, bạn sẽ nhận được thông báo lỗi cho biết cơ sở dữ liệu hoặc nhà cung cấp OLE DB không thể bắt đầu giao dịch. Để xác định mức hỗ trợ giao dịch, bạn có thể sử dụng thuộc tính DDL giao dịch động của kết nối:

nếu ADOConnection1.Properties["Transaction DDL"].Value > DBPROPVAL_TC_NONE thì ADOConnection1.BeginTrans;


Nếu bạn cố gắng truy cập vào cùng một cơ sở dữ liệu Paradox bằng cách sử dụng nhà cung cấp Jet 4.0 OLE DB, sẽ không có lỗi xảy ra, nhưng do các hạn chế của nhà cung cấp, bạn sẽ không thể khôi phục giao dịch.
Một điểm khác biệt kỳ lạ khác xảy ra khi làm việc với Access: nếu bạn sử dụng nhà cung cấp ODBC OLE DB, bạn sẽ có thể sử dụng các giao dịch nhưng sẽ không thể sử dụng các giao dịch lồng nhau. Cố gắng mở một giao dịch mới song song với một giao dịch đang hoạt động hiện có sẽ dẫn đến lỗi. Tuy nhiên, nếu bạn sử dụng Jet engine, bạn sẽ có thể sử dụng các giao dịch lồng nhau mà không gặp vấn đề gì.

Giao dịch lồng nhau

Sử dụng TransProcessing, hãy thử bài kiểm tra sau.

    Kích hoạt giao dịch.

    Thay đổi trường Tên liên hệ của mục nhập Around The Horn từ Thomas Hardy thành Dick Solomon.

    Kích hoạt một giao dịch lồng nhau khác.

    Thay đổi trường Tên liên hệ của bản ghi Thị trường đô la đáy từ Elizabeth Lincoln thành Sally Solomon.

    Khôi phục giao dịch nội bộ.

    Xác nhận giao dịch bên ngoài.

Do đó, chỉ nên thực hiện sửa đổi đối với mục nhập Around The Horn. Nếu giao dịch nội bộ được cam kết và bạn khôi phục giao dịch bên ngoài, kết quả sẽ là không có thay đổi nào được thực hiện đối với cơ sở dữ liệu (ngay cả những thay đổi được thực hiện như một phần của giao dịch nội bộ). Đây là cách các giao dịch lồng nhau hoạt động. Có một hạn chế: Access chỉ hỗ trợ năm cấp độ lồng giao dịch.
ODBC không hỗ trợ các giao dịch lồng nhau và nhà cung cấp Jet OLE DB hỗ trợ tối đa năm cấp độ lồng nhau. Nhà cung cấp SQL Server OLE DB hoàn toàn không hỗ trợ lồng giao dịch. Bạn nên lưu ý rằng việc lồng giao dịch có thể được xử lý khác nhau tùy thuộc vào phiên bản của trình điều khiển hoặc máy chủ SQL. Các thông tin cần thiết có thể thu được từ tài liệu và thông qua các thí nghiệm. Có vẻ như trong hầu hết các trường hợp, giao dịch bên ngoài xác định liệu những thay đổi được thực hiện trong giao dịch bên trong có được thực hiện đối với cơ sở dữ liệu hay không.

Thuộc tính thành phần ADOConnection

Nếu bạn định sử dụng các giao dịch lồng nhau, có một điều nữa bạn cần tính đến. Thành phần ADOConnection có thuộc tính Thuộc tính xác định cách hoạt động của kết nối khi giao dịch được thực hiện hoặc được khôi phục. Thuộc tính Thuộc tính lưu trữ một tập hợp các giá trị TXActAttribut, ban đầu trống. Bảng liệt kê TXActAttribution chỉ bao gồm hai giá trị: xaCommitRetaining và xaAbortRetaining (giá trị này đôi khi được viết không chính xác là xaRollbackRetaining, vì về mặt logic thì đây là tên chính xác hơn). Nếu thuộc tính xaCommitRetaining có trong thuộc tính Thuộc tính, giao dịch mới sẽ tự động được mở khi giao dịch được thực hiện. Nếu thuộc tính xaAbortRetaining có trong thuộc tính Thuộc tính, giao dịch mới sẽ tự động được mở khi giao dịch được khôi phục. Do đó, nếu bạn thêm cả hai thuộc tính này vào thuộc tính Thuộc tính, mọi hành động sẽ được thực hiện trong khuôn khổ giao dịch: khi giao dịch tiếp theo hoàn tất, giao dịch tiếp theo sẽ tự động được kích hoạt.
Trong hầu hết các trường hợp, các lập trình viên không muốn làm việc ở chế độ này và kiểm soát độc lập việc mở giao dịch, vì vậy các thuộc tính này hiếm khi được sử dụng. Cần cân nhắc việc sử dụng các thuộc tính này cùng với các giao dịch lồng nhau. Nếu bạn tạo một giao dịch lồng nhau và đặt thuộc tính Thuộc tính thành , giao dịch bên ngoài sẽ không bao giờ hoàn thành. Chúng ta hãy xem xét chuỗi sự kiện này.

    Giao dịch bên ngoài bắt đầu.

    Giao dịch nội bộ bắt đầu.

    Một giao dịch nội bộ đang được cam kết hoặc được khôi phục.

Dựa trên cài đặt của thuộc tính Thuộc tính, giao dịch nội bộ mới sẽ tự động được bắt đầu.
Do đó, một giao dịch bên ngoài có thể không bao giờ hoàn thành, vì các giao dịch nội bộ luôn gắn bó với nhau. Chúng ta có thể kết luận rằng thuộc tính Thuộc tính và việc sử dụng các giao dịch lồng nhau là loại trừ lẫn nhau.

Các loại khóa

ADO hỗ trợ bốn cách tiếp cận khác nhau để chặn dữ liệu cập nhật: ltReadOnly, ltPessimistic, ltOptimistic và ltBatchOptimistic (cũng có loại ltUnspecified nhưng vì những lý do đã nêu trước đó, loại này không được sử dụng trong Delphi). Để định cấu hình chế độ khóa, hãy sử dụng thuộc tính LockType. Trong phần này, tôi sẽ nói ngắn gọn về cả bốn phương pháp chặn. Mỗi phương pháp này sẽ được thảo luận chi tiết hơn trong các phần tiếp theo.
Giá trị ltReadOnly chỉ ra rằng dữ liệu ở chế độ chỉ đọc - không thể cập nhật. Vì máy khách không thể sửa đổi dữ liệu nên không cần khóa.
Các giá trị ltPessimistic và ltOptimistic tương ứng cung cấp khả năng chặn bi quan và lạc quan. Các chế độ này tương đương với các chế độ BDE tương ứng. Tuy nhiên, so với BDE, công nghệ ADO mang lại sự linh hoạt cao hơn: việc lựa chọn chế độ chặn là của bạn. Nếu bạn đang sử dụng BDE, quyết định sử dụng khóa bi quan hay lạc quan sẽ do trình điều khiển BDE đưa ra cho bạn. Nếu bạn đang sử dụng cơ sở dữ liệu trên máy tính để bàn như Paradox hoặc dBase thì trình điều khiển BDE đang sử dụng khóa bi quan. Nếu bạn đang sử dụng cơ sở dữ liệu máy khách-máy chủ như InterBase, SQLServer hoặc Oracle, trình điều khiển BDE sẽ sử dụng khóa tối ưu.

Khóa bi quan

Trong bối cảnh này, các thuật ngữ “lạc quan” và “bi quan” mô tả kỳ vọng của người lập trình về khả năng xung đột khi cập nhật đồng thời dữ liệu có trong cơ sở dữ liệu bởi nhiều người dùng. Sự ngăn cản bi quan cho thấy khả năng xảy ra xung đột là rất cao. Nói cách khác, người dùng sửa đổi dữ liệu có trong cơ sở dữ liệu cùng một lúc và có khả năng cao là hai người dùng sẽ cố gắng sửa đổi cùng một bản ghi cơ sở dữ liệu cùng một lúc. Để ngăn chặn xung đột như vậy, bản ghi sẽ bị khóa vào thời điểm bắt đầu chỉnh sửa. Mục nhập vẫn bị khóa cho đến khi chỉnh sửa hoàn tất hoặc bị hủy. Nếu bất kỳ người dùng nào khác cố gắng chỉnh sửa cùng một mục nhập (đã bị khóa), họ sẽ không thể làm như vậy: ngoại lệ "Không thể thực hiện cập nhật, mục nhập bị khóa" sẽ được đưa ra.
Cách tiếp cận này sẽ quen thuộc với các lập trình viên trước đây đã từng làm việc với cơ sở dữ liệu trên máy tính để bàn như dBase và Paradox. Ưu điểm là người dùng biết rằng khi bắt đầu chỉnh sửa bản ghi, họ có thể hoàn thành chỉnh sửa và thực hiện các sửa đổi đối với cơ sở dữ liệu một cách thành công. Điểm bất lợi là người dùng có toàn quyền kiểm soát việc chặn bản ghi. Nếu người dùng thành thạo ứng dụng, việc chỉnh sửa một mục có thể chỉ mất vài giây, nhưng trong môi trường máy khách-máy chủ có nhiều người dùng, thậm chí một vài giây có thể dài như vô tận. Mặt khác, một người dùng không nghi ngờ có thể bắt đầu chỉnh sửa một bài đăng và đi ăn trưa. Trong trường hợp này, lối vào sẽ vẫn bị chặn cho đến khi anh ta quay lại nơi làm việc của mình. Trừ khi bạn thực hiện bất kỳ biện pháp đặc biệt nào, trong thời gian này sẽ không ai có thể chỉnh sửa mục bị chặn. Để tránh điều này, họ thường sử dụng bộ hẹn giờ: nếu bàn phím và chuột không hoạt động trong một thời gian dài, chương trình sẽ tự động mở khóa ghi âm.
Một vấn đề khác với việc chặn bi quan là việc chặn bi quan yêu cầu con trỏ phía máy chủ. Chúng ta đã thảo luận trước đó rằng vị trí con trỏ ảnh hưởng đến các loại con trỏ có sẵn. Bây giờ chúng ta thấy rằng vị trí của con trỏ cũng ảnh hưởng đến các phương pháp chặn. Chúng ta sẽ thảo luận chi tiết hơn về lợi ích của việc sử dụng con trỏ phía máy khách ở phần sau của chương này. Nếu quyết định tận dụng những lợi ích này thì bạn sẽ không thể tận dụng được thế khóa bi quan.

Cập nhật dữ liệu

Hỗ trợ các kết nối có thể cập nhật là một trong những lý do chính khiến các lập trình viên sử dụng thành phần ClientDataSet (hoặc các bản cập nhật được lưu trong bộ nhớ đệm trong BDE). Một truy vấn liên quan đến việc nối hai bảng sẽ trả về một bảng duy nhất cho người dùng và người dùng muốn có thể sửa đổi các bản ghi trong bảng đó. Hãy xem xét câu lệnh SQL sau:

CHỌN * TỪ Sản phẩm, Nhà cung cấp Ở ĐÂU Nhà cung cấp.SupNo=Products.SupNo

Truy vấn này trả về danh sách các sản phẩm cùng với các nhà cung cấp cung cấp các sản phẩm đó. Công cụ BDE xử lý mọi kết nối SQL dưới dạng bảng chỉ đọc. Vấn đề là việc thêm, cập nhật và xóa các bản ghi trong một bảng đã nối là không rõ ràng. Ví dụ: nếu người dùng thêm bản ghi mới vào bảng đã hợp nhất, thì nhà cung cấp mới và sản phẩm mới có nên được thêm vào bảng hay chỉ giới hạn ở việc thêm một sản phẩm? Kiến trúc ClientDataSet/Provider cho phép bạn chỉ định bảng chính cần cập nhật (cuốn sách này không đề cập đến vấn đề đó) và định cấu hình thêm các bản cập nhật SQL. Điều này được đề cập một phần trong Chương 14 và tôi cũng sẽ đề cập đến nó trong Chương 16. ADO hỗ trợ một cơ chế lưu vào bộ nhớ đệm cập nhật được gọi là cập nhật hàng loạt, hoạt động gần giống như của BDE. Trong phần tiếp theo, tôi sẽ xem xét kỹ hơn cơ chế cập nhật hàng loạt của ADO. Tuy nhiên, để giải quyết vấn đề cập nhật kết nối SQL, bạn có thể thực hiện mà không cần sự trợ giúp của cơ chế này. Thực tế là ADO hỗ trợ cập nhật các kết nối SQL. Thành phần ADODataset đã được thêm vào chương trình JoinData, dựa trên biểu thức SQL được đưa ra trước đó. Nếu chạy chương trình, bạn có thể chỉnh sửa một trong các trường và lưu các thay đổi vào cơ sở dữ liệu (để thực hiện việc này, chỉ cần di chuyển sang bản ghi khác). Sẽ không có lỗi xảy ra vì ADO sẽ cập nhật cơ sở dữ liệu thành công. Thực tế là, không giống như BDE, ADO có cách tiếp cận thực tế hơn. Trong ADO, khi bạn nối nhiều bảng, mỗi trường sẽ biết nó thuộc về bảng nào. Nếu bạn cập nhật một trường trong bảng Sản phẩm và xuất bản các thay đổi đối với cơ sở dữ liệu thì bản cập nhật sẽ tạo ra câu lệnh UPDATE SQL cập nhật giá trị của trường trong bảng Sản phẩm của cơ sở dữ liệu. Nếu, ngoài trường bảng Sản phẩm, bạn cũng thay đổi trường bảng Nhà cung cấp thì hai câu lệnh SQL CẬP NHẬT sẽ được tạo - một câu lệnh cho mỗi bảng.
Khi thêm dòng mới Trong kết nối SQL, cơ chế ADO hoạt động theo cách tương tự. Nếu bạn chèn một hàng và chỉ thêm giá trị cho các trường trong bảng Sản phẩm thì chỉ có một câu lệnh SQL INSERT được tạo để thêm bản ghi mới vào bảng Sản phẩm. Nếu bạn nhập giá trị cho các trường trong cả hai bảng, hai câu lệnh SQL INSERT sẽ được tạo, một câu lệnh cho mỗi bảng. Thứ tự thực hiện các biểu thức này rất quan trọng vì một sản phẩm mới có thể tham chiếu một nhà cung cấp mới, vì vậy thông tin nhà cung cấp trước tiên phải được thêm vào bảng Nhà cung cấp. Sự cố nghiêm trọng xảy ra khi bạn xóa một hàng khỏi bảng đã nối. Khi bạn cố xóa một hàng khỏi bảng đã nối, bạn sẽ thấy thông báo lỗi. Nội dung chính xác của thông báo tùy thuộc vào phiên bản ADO cũng như cơ sở dữ liệu được sử dụng. Thông báo này có thể gây nhầm lẫn vì rất có thể nó sẽ không liên quan gì đến nguyên nhân thực sự của vấn đề. Vấn đề là bạn không thể xóa bản ghi được tham chiếu bởi các bản ghi khác. Trong ví dụ của chúng tôi, bạn có thể thấy thông báo cho biết rằng không thể xóa bản ghi sản phẩm vì có những bản ghi khác tham chiếu bản ghi đó. Tuy nhiên, nếu bạn thực hiện một vài thử nghiệm, bạn sẽ thấy rằng lỗi xảy ra bất kể có bản ghi nào khác trong cơ sở dữ liệu tham chiếu đến sản phẩm đang bị xóa hay không hoặc không có bản ghi nào như vậy. Để hiểu nguyên nhân của vấn đề, bạn cần sử dụng cách tiếp cận tương tự như khi thêm bản ghi mới vào bảng đã nối. Khi một hàng trong bảng đã nối bị xóa, ADO sẽ tạo hai câu lệnh SQL DELETE: một cho bảng Nhà cung cấp và một cho bảng Sản phẩm. Câu lệnh DELETE cho bảng Sản phẩm thành công nhưng câu lệnh DELETE cho bảng Nhà cung cấp không thành công - không thể xóa một nhà cung cấp sản phẩm khỏi bảng vì nó thường có nhiều bản ghi sản phẩm tham chiếu đến nó.

Nếu bạn muốn xem chính xác câu lệnh SQL nào được tạo khi chạy một lệnh ADO cụ thể, hãy nhớ rằng nếu bạn đang sử dụng SQL Server, bạn có thể xem các biểu thức này bằng công cụ SQL Server Profiler.

Ngay cả khi bạn hiểu chính xác cách thức hoạt động của quy trình, việc xem xét vấn đề qua con mắt của người dùng vẫn rất hữu ích. Tôi cá rằng khi người dùng xóa một bản ghi khỏi một bảng đã tham gia, 99% họ dự định chỉ xóa bản ghi sản phẩm, giữ nguyên bản ghi nhà cung cấp. May mắn thay, bạn có thể đạt được kết quả này nếu bạn sử dụng thuộc tính động đặc biệt của Bảng duy nhất. Với nó, bạn có thể chỉ định rằng việc xóa một hàng chỉ ảnh hưởng đến bảng Sản phẩm chứ không ảnh hưởng đến bảng Nhà cung cấp. Đoạn mã sau được sử dụng cho việc này:

ADOQuery1.Properties["Bảng duy nhất"].Value:= "Sản phẩm";

Bạn không thể gán giá trị cho thuộc tính này tại thời điểm thiết kế, vì vậy biểu thức này phải được đặt trong trình xử lý sự kiện OnCreate.

Cập nhật hàng loạt

Khi sử dụng cơ chế cập nhật hàng loạt, mọi thay đổi do người dùng thực hiện sẽ được tích lũy trong bộ nhớ cục bộ. Sau đó gói đầy đủ những thay đổi này có thể được thực hiện đối với cơ sở dữ liệu trong một thao tác. Rõ ràng, cách tiếp cận này mang lại lợi ích về hiệu suất nhưng cũng có những ưu điểm khác khiến nó trở nên thuận tiện. Đặc biệt, khi sử dụng cơ chế cập nhật hàng loạt, người dùng có thể thực hiện các thay đổi ngay cả khi bị ngắt kết nối khỏi cơ sở dữ liệu. Tính năng này có thể được sử dụng để cung cấp trải nghiệm người dùng ở chế độ ngoại tuyến, sử dụng các công nghệ như Briefcase, cũng như trong các ứng dụng web dựa trên cơ chế ADO khác có tên RDS (Dịch vụ dữ liệu từ xa). Bạn có thể bật cập nhật hàng loạt cho bất kỳ tập dữ liệu ADO nào. Để thực hiện việc này, bạn phải đặt thuộc tính LockType thành ltBatchOptimistic trước khi mở tập dữ liệu. Ngoài ra, bạn phải đặt thuộc tính CursorLocation thành clUseClient vì các cập nhật hàng loạt được xử lý bởi Công cụ con trỏ ADO. Do đó, mọi thay đổi mà người dùng thực hiện đối với tập dữ liệu sẽ được lưu trữ trong vùng delta (khu vực này lưu trữ danh sách các thay đổi). Tập dữ liệu sẽ xuất hiện như thể dữ liệu đã được thay đổi, nhưng trên thực tế thông tin về những thay đổi được lưu trữ trong bộ nhớ - những thay đổi này không được thực hiện đối với cơ sở dữ liệu. Để xuất bản các thay đổi đối với cơ sở dữ liệu (chuyển chúng từ bộ nhớ sang cơ sở dữ liệu), bạn cần gọi phương thức ApplyBatch (phương thức này tương đương với phương thức ApplyUpdates của cơ chế BDE):

ADODataSet1.UpdateBatch;

Nếu bạn muốn hủy mọi thứ được tích lũy trong bộ nhớ, hãy sử dụng phương thức CancelBatch - đây là phương thức tương tự của phương thức CancelUpdates. Có nhiều phương thức và thuộc tính khác có tên tương tự được sử dụng trong Cập nhật hàng loạt ADO, Cập nhật bộ đệm BDE và cơ chế bộ đệm ẩn Bộ dữ liệu máy khách. Ví dụ: như trong BDE, thuộc tính UpdateStatus của tập dữ liệu ADO có thể được sử dụng để tìm hiểu trạng thái của một bản ghi nhất định: liệu bản ghi đã được thêm, sửa đổi, xóa hay chưa trải qua bất kỳ thay đổi nào. Thuộc tính này rất hữu ích nếu bạn muốn đánh dấu các mục đã sửa đổi bằng màu sắc hoặc hiển thị trạng thái của chúng trên thanh trạng thái. Có một số khác biệt về cú pháp, ví dụ: thay vì gọi RevertRecord trong ADO, việc gọi CancelBatch(arCurrent); được sử dụng. Một tính năng rất hữu ích của cơ chế cập nhật được lưu trong bộ nhớ đệm của BDE bị thiếu trong ADO: cơ chế theo dõi xem các bản cập nhật có tồn tại chưa được xuất bản lên cơ sở dữ liệu hay không. BDE sử dụng thuộc tính UpdatesPending cho mục đích này. Thuộc tính này chứa giá trị True nếu các thay đổi đã được thực hiện đối với tập dữ liệu chưa được xuất bản lên cơ sở dữ liệu. Thuộc tính này thuận tiện để sử dụng trong trình xử lý sự kiện OnCloseQuery:

Tuy nhiên, việc có kiến thức cần thiết và sáng tạo, bạn có thể viết hàm ADOUpdatesPending của riêng mình. Để viết một hàm như vậy, bạn phải biết rằng bộ dữ liệu ADO hỗ trợ thuộc tính FilterGroup, có chức năng giống như một bộ lọc. Không giống như thuộc tính Filter của tập dữ liệu tiêu chuẩn lọc dữ liệu dựa trên một số điều kiện, thuộc tính FilterGroup có thể lọc dựa trên trạng thái của bản ghi. Có một số trạng thái lọc và một trong số chúng tương ứng với giá trị fgPendingRecords. Trạng thái này tương ứng với các bản ghi đã được sửa đổi nhưng thông tin thay đổi chưa được công bố trong cơ sở dữ liệu. Vì vậy, để xem tất cả những thay đổi đã được thực hiện nhưng chưa được công bố, bạn chỉ cần chạy hai dòng mã:

ADODataSet1.FilterGroup:= fgPendingRecords; ADODataSet1.Filtered:= Đúng;

Đương nhiên, sau khi thực hiện các lệnh này, tập dữ liệu sẽ chứa các bản ghi đã bị xóa và các trường của các bản ghi này sẽ trống - điều này không thuận tiện lắm vì bạn sẽ không thể hiểu bản ghi nào đã bị xóa. (Phiên bản đầu tiên của ADOExpress hoạt động khác: tất cả các giá trị trường được hiển thị cho các bản ghi đã xóa.)
Để giải quyết vấn đề Cập nhật đang chờ xử lý, bạn sẽ cần sử dụng nhân bản tập dữ liệu (tính năng này đã được thảo luận trước đó). Hàm ADOUpdatesPending đặt thuộc tính FilterGroup sao cho tập dữ liệu chỉ chứa thông tin về những thay đổi đã thực hiện nhưng chưa được xuất bản. Bây giờ chúng ta cần kiểm tra xem có ít nhất một bản ghi trong tập dữ liệu hay không. Nếu có ít nhất một mục nhập, điều đó có nghĩa là một số thay đổi chưa được công bố trong cơ sở dữ liệu. Nếu sau khi lọc, tập dữ liệu trống, điều đó có nghĩa là tất cả các thay đổi được thực hiện trước đó đã được xuất bản trong cơ sở dữ liệu. Tuy nhiên, nếu bạn cố kiểm tra số lượng bản ghi trong tập dữ liệu thực, việc đặt lại thuộc tính FilterGroup sẽ bù con trỏ tới bản ghi hiện tại - giao diện người dùng sẽ phản hồi ngay lập tức với điều này. Để tránh điều này, hãy sử dụng bản sao tập dữ liệu:

chức năng ADOUpdatePending(ADODataSet: TCustomADODataSet): boolean; var Bản sao: ​​TADODataSet; bắt đầu Bản sao:= TADODataSet.Create(nil); thử Clone.Clone(ADODataSet); Clone.FilterGroup:= fgPendingRecords; Clone.Filtered:= Đúng; Kết quả:= không (Clone.BOF và Clone.EOF); Bản sao.Đóng; Cuối cùng Bản sao.Miễn phí; kết thúc; kết thúc;

Trong hàm này, bạn sao chép tập dữ liệu gốc, đặt thuộc tính FilterGroup rồi kiểm tra xem liệu con trỏ có ở cả đầu và cuối tập dữ liệu hay không. Nếu vậy thì tập dữ liệu trống.

Khóa lạc quan

Trước đây, chúng ta đã xem xét việc sử dụng thuộc tính LockType và thảo luận về cách hoạt động của khóa bi quan. Trong phần này chúng ta sẽ xem xét khóa lạc quan. Khóa lạc quan không chỉ được ưu tiên cho các hệ thống hiệu suất cao mà còn là loại khóa được sử dụng khi thực hiện cập nhật hàng loạt.
Khóa lạc quan giả định rằng xung đột giữa hai người dùng cố gắng chỉnh sửa cùng một mục tại cùng một thời điểm khó có thể xảy ra. Theo đó, bất kỳ người dùng nào cũng được phép chỉnh sửa bất kỳ mục nào vào bất kỳ lúc nào. Hậu quả của xung đột được xử lý khi các thay đổi được lưu vào cơ sở dữ liệu. Vì vậy, xung đột được coi là ngoại lệ đối với quy tắc. Nếu hai người dùng cố gắng lưu các thay đổi vào cùng một bản ghi thì chỉ người dùng đầu tiên mới có thể thực hiện việc đó; Hiện tượng này xảy ra trong các ứng dụng chạy theo mô hình Cặp tài liệu, cũng như trong các ứng dụng web không có kết nối liên tục với cơ sở dữ liệu và do đó không thể triển khai khóa bi quan. Không giống như khóa bi quan, khóa lạc quan không yêu cầu chặn tài nguyên lâu dài: bản ghi chỉ bị khóa tại thời điểm cập nhật. Do đó, trung bình mức tiêu thụ tài nguyên thấp hơn và cơ sở dữ liệu có khả năng mở rộng cao hơn.
Hãy xem một ví dụ. Hãy tưởng tượng bạn có một thành phần ADODataSet được kết nối với bảng Khách hàng từ ví dụ dbdemos.mdb; thuộc tính LockType được đặt thành ltBatchOptimistic và nội dung của tập dữ liệu được hiển thị trong DBGrid. Cũng giả sử rằng bạn có một nút mà khi được nhấp vào sẽ gọi phương thức UpdateBatch. Chạy hai bản sao của chương trình này (đây là chương trình BatchUpdates). Bắt đầu chỉnh sửa mục trong bản sao đầu tiên của chương trình. Để đơn giản, tôi sử dụng một máy tính trong phần trình diễn này, nhưng điều tương tự sẽ xảy ra nếu bạn chỉnh sửa cùng một bản ghi trên hai máy tính.

    Chọn Thị trường đồng đô la đáy ở Canada và đổi tên thành Thị trường đồng đô la đáy.

    Lưu các thay đổi vào cơ sở dữ liệu; để thực hiện việc này, chỉ cần chuyển đến bản ghi khác và nhấp vào nút cập nhật hàng loạt.

    Trong bản sao thứ hai của chương trình, tìm mục nhập tương tự và đổi tên công ty thành Bottom-Pound Markets.

    Điều hướng đến mục khác và nhấp vào nút cập nhật hàng loạt. Bản cập nhật sẽ không hoạt động.

Giống như các thông báo lỗi ADO khác, nội dung của thông báo sẽ không chỉ phụ thuộc vào phiên bản ADO mà còn phụ thuộc vào mức độ bạn tuân thủ chặt chẽ chuỗi hành động được mô tả. Trong ADO 2.6, bạn sẽ thấy thông báo lỗi sau trên màn hình: Không thể định vị hàng để cập nhật. Một số giá trị có thể đã được thay đổi kể từ lần đọc cuối cùng. Không thể tìm thấy hàng cần cập nhật. Một số giá trị của hàng có thể đã thay đổi kể từ lần đọc cuối cùng.
Đây là toàn bộ quan điểm của việc ngăn chặn lạc quan. Để cập nhật một bản ghi, câu lệnh SQL sau được thực thi:

CẬP NHẬT KHÁCH HÀNG CompanyName="Bottom-Pound Markets" WHERE CustomerID="BOTTM" AND CompanyName="Bottom-Pound Markets"

Biểu thức xác định một bản ghi bằng cách sử dụng khóa chính và giá trị của trường Tên công ty giống như khi bản ghi được đọc từ cơ sở dữ liệu vào bộ nhớ. Dự kiến ​​một bản ghi bảng sẽ được sửa đổi do thực hiện biểu thức này. Tuy nhiên, trong ví dụ chúng ta đã xem xét, không có bản ghi nào bị sửa đổi do thực thi biểu thức. Kết quả này chỉ có thể xảy ra nếu bản ghi bị xóa, khóa chính thay đổi hoặc trường đang được sửa đổi đã được ai đó sửa đổi trước bạn. Trong bất kỳ trường hợp nào, quá trình cập nhật sẽ không thành công.
Nếu người dùng thứ hai cố gắng thay đổi giá trị của trường Tên liên hệ (chứ không phải Tên công ty), thì biểu thức cập nhật sẽ như sau:

CẬP NHẬT KHÁCH HÀNG THIẾT LẬP ContactName="Liz Lincoln" WHERE CustomerID="BOTTM" AND ContactName="Elizabeth Lincoln"

Trong trường hợp của chúng tôi, quá trình cập nhật sẽ thành công vì người dùng khác sẽ không thay đổi khóa chính hoặc tên liên hệ. Hành vi này tương tự như chế độ Cập nhật nơi đã thay đổi của cơ chế BDE. Thay vì thuộc tính UpdateMode được sử dụng trong BDE, ADO sử dụng thuộc tính Tiêu chí cập nhật tập dữ liệu động. Danh sách sau đây chứa các giá trị hợp lệ cho thuộc tính động này.

Đừng cho rằng một trong những chế độ này sẽ thích hợp hơn cho toàn bộ ứng dụng của bạn. Trong thực tế, việc lựa chọn chế độ được xác định bởi loại thông tin có trong bảng. Giả sử bảng Khách hàng chỉ có ba trường: ID khách hàng, Tên và Thành phố. Việc thay đổi bất kỳ trường nào trong số này không ảnh hưởng đến giá trị của các trường khác trong bảng, vì vậy trong tình huống như vậy, bạn hoàn toàn có thể sử dụng chế độ adCriteriaUpdCols (chế độ này được sử dụng theo mặc định). Tuy nhiên, nếu ngoài các trường được liệt kê, bảng còn bao gồm trường Mã bưu điện ( mã bưu điện), thì việc cập nhật trường này phải được phối hợp với việc cập nhật trường Thành phố. Nói cách khác, bạn không thể cho phép một người dùng sửa đổi trường Mã bưu chính và đồng thời một người dùng khác sửa đổi trường Thành phố mà không có bất kỳ thỏa thuận nào với người dùng đầu tiên. Trong trường hợp này, chế độ cập nhật adCriteriaAllCols sẽ an toàn hơn. Bạn cũng nên nói về cách ADO xử lý lỗi khi cập nhật nhiều bản ghi. Trong BDE và ClientDataSet, bạn có thể sử dụng sự kiện OnUpdateError cho mục đích này, sự kiện này sẽ cho phép bạn phản hồi lỗi liên quan đến cập nhật bản ghi và giải quyết vấn đề trước khi chuyển sang bản ghi tiếp theo. Không có tùy chọn như vậy trong ADO. Bạn có thể theo dõi tiến trình, thành công hay thất bại của bản cập nhật hàng loạt bằng cách sử dụng các sự kiện OnWillChangeRecord và OnRecordChangeComplete, nhưng bạn không thể thay đổi nội dung của bản ghi đang được cập nhật và cố gắng đưa nó vào cơ sở dữ liệu, như có thể trong BDE và ClientDataSet . Một vấn đề khác là nếu xảy ra lỗi trong quá trình cập nhật hàng loạt, quy trình cập nhật không dừng mà vẫn tiếp tục chạy. Việc cập nhật hàng loạt được thực hiện cho đến khi kết thúc, nghĩa là cho đến khi tất cả các thay đổi được thực hiện đối với cơ sở dữ liệu (các lỗi khác có thể xảy ra trong trường hợp này). Kết quả là bạn có thể nhận được thông báo lỗi khó hiểu hoặc không chính xác. Nếu xảy ra nhiều lỗi trong quá trình cập nhật hàng loạt (không thể cập nhật nhiều bản ghi), ADO 2.6 sẽ hiển thị thông báo sau trên màn hình: Lỗi tạo ra thao tác OLE DB nhiều bước. Kiểm tra từng giá trị trạng thái OLE DB, nếu có. Không có công việc nào được thực hiện. Đã xảy ra lỗi trong quá trình thao tác OLE DB nhiều bước. Nếu có thể, hãy kiểm tra từng trạng thái OLE DB. Vấn đề nằm ở câu cuối cùng: Không có công việc nào được thực hiện. ADO cho chúng ta biết rằng chưa có gì được thực hiện, nhưng thực tế không phải vậy. Bản ghi gây ra lỗi thực sự chưa được cập nhật nhưng tất cả các bản ghi khác đã được xuất bản thành công vào cơ sở dữ liệu.

Giải quyết xung đột cập nhật dữ liệu

Trong quá trình cập nhật, cách tiếp cận sau sẽ hợp lý: người dùng thực hiện các thay đổi cần thiết đối với tập dữ liệu, sau đó thực hiện cập nhật hàng loạt, xảy ra lỗi khi cập nhật một số bản ghi, khi quá trình cập nhật hoàn tất, người dùng sẽ nhận được một danh sách các hồ sơ có vấn đề và có cơ hội giải quyết từng xung đột. Để có danh sách tất cả các bản ghi có vấn đề, bạn có thể sử dụng giá trị fgConflictingRecords của thuộc tính FilterGroup:

ADODataSet1.FilterGroup:= fgConflictingRecords; ADODataSet1.Filtered:= Đúng;

Đối với mỗi trường của mỗi bản ghi có vấn đề, bạn có thể cho người dùng biết ba giá trị chính: giá trị của trường có trong bản ghi tại thời điểm bản ghi này được đọc lần đầu từ cơ sở dữ liệu; giá trị trường được người dùng này gán cho trường; giá trị hiện có trong cơ sở dữ liệu (nghĩa là trong quá trình cập nhật). Các thuộc tính Tfield sau đây được sử dụng cho việc này.

Những người làm việc với thành phần ClienDataSet đều biết về sự tồn tại của hộp thoại ReconcileErrorForm tiện lợi. Hộp thoại này được tạo tự động, hiển thị cho người dùng các giá trị trường cũ, mới và hiện tại của bản ghi có vấn đề và cho phép người dùng chọn phương pháp giải quyết xung đột. Thật không may, không có hộp thoại tương tự nào trong ADO. Lớp TReconcileErrorForm được thiết kế riêng cho thành phần ClientDataSet nên rất khó điều chỉnh để sử dụng với các bộ dữ liệu ADO. Cũng cần nói về thứ tự hoạt động của các thuộc tính được đề cập của lớp TField. Các thuộc tính này dựa trên các đối tượng Trường ADO mà chúng tham chiếu đến. Điều này có nghĩa là cách thức hoạt động của các thuộc tính này hoàn toàn được xác định bởi nhà cung cấp OLE DB mà bạn đang sử dụng. Bạn chỉ có thể hy vọng rằng nhà cung cấp bạn đang sử dụng hỗ trợ chính xác những tính năng bạn cần. Hầu hết các nhà cung cấp đều thực hiện tốt việc này, nhưng nhà cung cấp Jet OLE DB trả về cùng một giá trị cho thuộc tính CurValue và OldValue. Chính xác hơn, giá trị hiện tại của trường trả về giá trị có trong trường khi bản ghi được đọc lần đầu từ cơ sở dữ liệu. Nói cách khác, Jet không cho phép bạn xác định giá trị được người dùng khác gán cho một trường (trừ khi bạn thực hiện một số bước bổ sung để tự mình thực hiện việc đó). Nếu bạn đang sử dụng nhà cung cấp OLEDB của SQL Server, bạn chỉ có thể truy cập thuộc tính CurValue sau khi phương thức Resync của tập dữ liệu được thực thi và tham số AffectRecords phải bằng giá trị của adAffectGroup và tham số ResyncValues ​​​​phải chứa giá trị của adResyncUnderlyingValues . Đây là mã có liên quan:

adoCustomers.FilterGroup:= fgConflictingRecords; adoCustomers.Filtered:= true; adoCustomers.Recordset.Resync(adAffectGroup, adResyncUnderlyingValues);

Tập bản ghi bị vô hiệu hóa

Bây giờ bạn đã biết về các bản cập nhật hàng loạt, chúng ta có thể bắt đầu khám phá một tính năng ADO khác: các tập bản ghi bị vô hiệu hóa. Tập bản ghi bị ngắt kết nối là tập bản ghi bị ngắt kết nối khỏi kết nối cơ sở dữ liệu. Người dùng có thể làm việc với một tập bản ghi như vậy theo cách giống hệt như cách họ làm việc với một tập bản ghi được kết nối thông thường. Đây là một tính năng rất ấn tượng: hầu như không có sự khác biệt giữa các tập bản ghi được kết nối và ngắt kết nối. Các thuộc tính và khả năng hầu như giống hệt nhau. Để ngắt kết nối một tập bản ghi khỏi một kết nối, bạn phải đặt thuộc tính CursorLocation thành clUseClient và thuộc tính LockType thành ltBatchOptimistic. Sau đó bạn đặt thuộc tính Connection thành nil, điều này làm cho tập bản ghi bị vô hiệu hóa:

Tính năng này cũng được hỗ trợ trong BDE và các công nghệ dữ liệu khác, nhưng để thực hiện được điều này, bạn phải chuyển sang sử dụng Bộ dữ liệu khách hàng. Cái hay của ADO là ngay từ đầu bạn có thể thiết kế ứng dụng của mình như thể bạn không hề biết rằng một tập bản ghi có thể bị ngắt kết nối khỏi cơ sở dữ liệu. Bạn sử dụng các thành phần dbGo bình thường theo cách thông thường nhất. Sau này, bạn có thể dễ dàng thêm khả năng ngắt kết nối khỏi cơ sở dữ liệu vào chương trình của mình như thể bạn vừa biết về sự tồn tại của khả năng này. Trong trường hợp này, bạn không cần thay đổi mã chính của ứng dụng.
Việc vô hiệu hóa một recordset có thể cần thiết để:

    giảm thiểu tổng số kết nối song song tới cơ sở dữ liệu;

    đảm bảo ứng dụng hoạt động offline (theo mô hình Briefcase).

Chúng ta sẽ nói về các ứng dụng hoạt động trong mô hình Cặp tài liệu ở một trong các phần sau.
Hầu hết các ứng dụng kinh doanh hoạt động theo khái niệm máy khách-máy chủ mở các bảng cơ sở dữ liệu và duy trì kết nối liên tục với cơ sở dữ liệu miễn là bảng được mở.
Tuy nhiên, trên thực tế, việc kết nối chỉ cần thiết trong hai thao tác: lấy dữ liệu từ cơ sở dữ liệu và cập nhật dữ liệu trong cơ sở dữ liệu. Hãy tưởng tượng nếu bạn sửa đổi chương trình của mình để ngắt kết nối khỏi cơ sở dữ liệu ngay sau khi mở bảng và truy xuất dữ liệu. Khi dữ liệu cần thiết được chuyển đến máy khách, kết nối sẽ bị chấm dứt. Đây là mã có liên quan:

Nếu bạn sử dụng cách tiếp cận tương tự trong ứng dụng của mình, số lượng kết nối cơ sở dữ liệu trung bình được mở cùng lúc sẽ ở mức tối thiểu - các kết nối sẽ chỉ được mở trong một thời gian ngắn khi chúng thực sự cần thiết. Rõ ràng, cấu trúc client-server như vậy dễ dàng mở rộng hơn nhiều. Máy chủ sẽ có thể phục vụ số lượng khách hàng lớn hơn đáng kể. Ngoài ra còn có một nhược điểm: việc hình thành kết nối tới một số (nhưng không phải tất cả) cơ sở dữ liệu đòi hỏi thời gian đáng kể, trong tình huống như vậy, việc cập nhật hàng loạt sẽ chậm hơn.

Nhóm kết nối

Nói đến việc phá vỡ và mở lại các kết nối khiến chúng ta băn khoăn liệu các kết nối có thể được sử dụng lại không? Cơ chế này được gọi là Kết nối tổng hợp. Khi sử dụng nó, khi ứng dụng kết thúc hoạt động với một kết nối, kết nối đó không bị hủy mà thay vào đó được đưa vào vùng lưu trữ (pool) và sau đó có thể được sử dụng lại. Tất nhiên, quá trình này là tự động, miễn là nhà cung cấp OLE DB mà bạn đang sử dụng hỗ trợ và cơ chế này được bật. Trong trường hợp này, không cần thực hiện thêm hành động nào.
Hiệu suất là lý do chính để sử dụng cơ chế như vậy. Thường mất thời gian để thiết lập kết nối tới cơ sở dữ liệu. Nếu bạn đang xử lý cơ sở dữ liệu trên máy tính như Access, kết nối sẽ được thiết lập hầu như ngay lập tức. Tuy nhiên, trong môi trường máy khách/máy chủ, chẳng hạn như máy chủ Oracle được truy cập qua mạng, có thể mất vài giây để thiết lập kết nối. Vì vậy, thật hợp lý khi nghĩ về tái sử dụng một nguồn tài nguyên có giá trị như một kết nối cơ sở dữ liệu.
Khi sử dụng cơ chế tích lũy của ADO, mỗi khi một ứng dụng "hủy" một đối tượng ADOConnection, đối tượng đó sẽ được thêm vào một nhóm đặc biệt (một vị trí lưu trữ tạm thời). Nếu cần tạo kết nối mới trong tương lai, hệ thống sẽ tự động tìm kiếm kết nối phù hợp trong nhóm. Nếu tìm thấy một kết nối hiện có có chuỗi kết nối phù hợp với chuỗi kết nối mà người dùng cần thì kết nối đó sẽ được sử dụng lại. Nếu không tìm thấy kết nối phù hợp, một kết nối sẽ được tạo. Các kết nối vẫn còn trong nhóm cho đến khi chúng được yêu cầu, ứng dụng thoát hoặc hết thời gian chờ. Khoảng thời gian chờ mặc định là 60 giây, nhưng bắt đầu với MDAC 2.5, giá trị này có thể được thay đổi. Để thực hiện việc này, bạn cần chỉ định khoảng thời gian chờ trong khóa đăng ký HKEY_CLASSES_ROOT\ CLSID\ \SPHết thời gian chờ. Quá trình tích lũy và tái sử dụng các kết nối được thực hiện một cách minh bạch mà không cần bất kỳ hành động bổ sung nào từ phía nhà phát triển. Một cơ chế tương tự để tích lũy kết nối hoạt động trong BDE khi sử dụng MTS (Máy chủ giao dịch Microsoft) và COM+, tuy nhiên, không giống như BDE, cơ chế ADO tích lũy kết nối một cách độc lập, không có Trợ giúp MTS hoặc COM+.
Theo mặc định, cơ chế tích lũy kết nối được bật cho tất cả các nhà cung cấp MDAC OLE DB Cơ sở dữ liệu quan hệ dữ liệu (bao gồm SQL Server và Oracle). Một ngoại lệ quan trọng là nhà cung cấp Jet OLE DB. Nếu bạn đang sử dụng ODBC, bạn có thể chọn giữa tích lũy kết nối ODBC và tích lũy kết nối ADO, tuy nhiên, không nên sử dụng cả hai cơ chế này cùng một lúc. Bắt đầu với MDAC 2.1, tính năng tổng hợp kết nối ADO được bật theo mặc định và tính năng tổng hợp kết nối ODBC bị tắt.

GHI CHÚ

Bất kể nhà cung cấp OLE DB, việc tích lũy kết nối không xảy ra trong môi trường Windows 95.

Thật không may, ADO không bao gồm các công cụ cho phép bạn giám sát nội dung của nhóm kết nối. Tuy nhiên, bạn có thể sử dụng công cụ SQL Server cho mục đích này Giám sát hiệu suất, sẽ cung cấp cho bạn thông tin về các kết nối tới cơ sở dữ liệu SQL Server.
Bạn có thể bật hoặc tắt tích lũy kết nối bằng cách sử dụng sổ đăng ký hoặc sử dụng chuỗi kết nối. Sổ đăng ký sử dụng tham số OLEDB_SERVICES cho mục đích này, tham số này nằm trong phần HKEY_CLASSES_ROOT\CLSID\ . Cài đặt này lưu trữ một mặt nạ bit cho phép bạn tắt một số dịch vụ OLE DB, bao gồm tích trữ kết nối, ghi nhật ký giao dịch và các dịch vụ khác. Để tắt tính năng tích lũy kết nối bằng chuỗi kết nối, hãy thêm chuỗi ký tự;OLE DB Services=-2 vào cuối chuỗi kết nối. Để bật tính năng tổng hợp kết nối cho nhà cung cấp Jet OLE DB, hãy thêm chuỗi;OLE DB Services=-1 vào cuối chuỗi kết nối. Điều này sẽ kích hoạt tất cả các dịch vụ OLE DB.

Lưu một tập hợp các bản ghi vào bộ nhớ vĩnh viễn (Persistent Recordset)

Khả năng lưu trữ một tập hợp các bản ghi trên ổ cứng của bạn là một phần quan trọng của ứng dụng Briefcase. Sử dụng tính năng này, bạn có thể lưu nội dung của tập bản ghi vào một tệp trên ổ cứng cục bộ của mình. Sau này bạn có thể tải dữ liệu từ tệp này vào tập bản ghi. Trong số các lợi ích khác, tính năng này cho phép các nhà phát triển tạo các ứng dụng một tầng thực sự - bạn có thể cài đặt ứng dụng cơ sở dữ liệu mà không cần cài đặt chính cơ sở dữ liệu đó. Nhờ đó, việc cài đặt chương trình cần rất ít dung lượng trên ổ cứng của máy khách. Để lưu tập dữ liệu vào ổ cứng của bạn, hãy sử dụng phương thức SaveToFile:

Cần lưu ý rằng (không giống như ClientDataSet) ADO không chứa hỗ trợ riêng cho định dạng XML - công cụ MSXML được sử dụng để tạo mã XML. Do đó, người dùng ứng dụng của bạn sẽ cần cài đặt Internet Explorer 5.0 hoặc tải xuống MSXML từ trang web của Microsoft.
Nếu bạn dự định lưu trữ dữ liệu cục bộ ở định dạng XML, hãy lưu ý một số nhược điểm của phương pháp này:

    Các tệp XML (được tạo bởi công cụ ADO, tuy nhiên, giống như bất kỳ tệp XML nào khác) có kích thước đáng kể, kích thước của chúng vượt quá đáng kể kích thước của tệp ADTG chứa cùng một dữ liệu (thường kích thước của tệp XML gấp đôi kích thước của một tệp XML). ADTG -file tương tự);

    XML do ADO tạo ra là một định dạng cụ thể của Microsoft (đây là trường hợp của nhiều công ty khác duy trì việc tạo XML của riêng họ), có nghĩa là ClientDataSet không thể đọc được XML do ADO tạo ra và ngược lại (may mắn thay, vấn đề này có thể được giải quyết. được giải quyết bằng cách sử dụng thành phần Chuyển đổi XML của Delphi, cho phép bạn chuyển đổi giữa các cấu trúc XML khác nhau).

Nếu bạn dự định chỉ sử dụng cơ chế lưu giữ tập bản ghi trong một ứng dụng một tầng và không có ý định sử dụng mô hình Briefcase thì bạn có thể sử dụng thành phần ADODataSet và đặt thuộc tính CommandType của nó thành cmdFile và thuộc tính CommandText của nó thành tên tệp. Điều này giúp loại bỏ sự cần thiết phải gọi phương thức LoadFromFile theo cách thủ công. Tuy nhiên, bạn vẫn sẽ phải gọi phương thức SaveToFile. Trong ứng dụng Cặp tài liệu, cách tiếp cận này sẽ quá hạn chế vì trong các ứng dụng như vậy, tập dữ liệu được sử dụng ở hai chế độ.

Mẫu vali

Bây giờ bạn đã quen với việc cập nhật hàng loạt, các tập bản ghi bị vô hiệu hóa và việc lưu trữ các tập bản ghi trong các tệp cục bộ, bạn có thể bắt đầu khám phá mô hình Cặp tài liệu. Ý tưởng chính là cung cấp cho người dùng khả năng làm việc với ứng dụng của bạn ngay cả khi họ không thể kết nối với cơ sở dữ liệu, tức là khi người dùng đang đi du lịch hoặc đang ở văn phòng của công ty khách hàng. Vấn đề là trong văn phòng của khách hàng, người dùng không thể kết nối với mạng công ty của công ty bạn, điều đó có nghĩa là anh ta không thể kết nối với máy chủ cơ sở dữ liệu. Điều này có nghĩa là dữ liệu không thể đến được máy tính xách tay của người dùng và được cập nhật.
Để cung cấp trải nghiệm ngoại tuyến cho người dùng, bạn sẽ cần các công nghệ như bộ dữ liệu bị vô hiệu hóa và lưu trữ bộ dữ liệu trên đĩa cục bộ. Hãy tưởng tượng rằng bạn đã phát triển một ứng dụng máy khách-máy chủ cung cấp quyền truy cập vào máy chủ cơ sở dữ liệu và đáp ứng đầy đủ nhu cầu của người dùng. Bây giờ người dùng yêu cầu bạn đảm bảo rằng ứng dụng này hoạt động ở chế độ ngoại tuyến, tức là ngay cả khi không có cách nào để kết nối với máy chủ cơ sở dữ liệu. Để làm được điều này, bạn phải thêm vào ứng dụng khả năng lưu dữ liệu trên ổ cứng cục bộ của người dùng. Nói cách khác, trước khi bắt đầu một cuộc hành trình, người dùng phải ra lệnh chuẩn bị ứng dụng để hoạt động ngoại tuyến. Lệnh này lưu mỗi bảng vào một tệp cục bộ bằng phương thức SaveToFile. Kết quả là một tập hợp các tệp ATDG hoặc XML trên ổ cứng của người dùng đại diện cho nội dung của cơ sở dữ liệu. Sau đó, người dùng có thể ngắt kết nối máy tính xách tay của mình khỏi mạng và tiếp tục làm việc với ứng dụng thông thường của mình ở chế độ ngoại tuyến.
Ứng dụng sẽ tự động phát hiện xem nó đang ngoại tuyến hay trực tuyến. Để xác định điều này, bạn có thể thử kết nối với cơ sở dữ liệu và kiểm tra xem kết nối có mở không. Bạn cũng có thể kiểm tra sự hiện diện của tệp danh mục đầu tư cục bộ hoặc sử dụng cờ đặc biệt của riêng bạn. Nếu ứng dụng đang chạy ngoại tuyến, thay vì kết nối với cơ sở dữ liệu, ứng dụng phải truy xuất dữ liệu từ tệp cục bộ bằng phương thức LoadFromFile. Khi bạn muốn xuất bản dữ liệu lên cơ sở dữ liệu, thay vì sử dụng phương thức UpdateBatches, ứng dụng của bạn nên gọi phương thức SaveToFile cho mỗi bảng. Nếu bạn có thể giao tiếp với cơ sở dữ liệu qua mạng, bạn phải đặt thuộc tính Connected của thành phần ADOConnection thành True, cũng như thuộc tính Active của từng thành phần ADODataSet. Khi người dùng trở về sau chuyến du lịch, anh ta phải nhập thông tin về những thay đổi mình đã thực hiện vào cơ sở dữ liệu. Để thực hiện việc này, bạn cần tải dữ liệu từ các tệp cục bộ, kết nối bộ dữ liệu với cơ sở dữ liệu và gọi phương thức UpdateBatch.

Đôi lời về ADO.NET

ADO.NET là một phần của kiến ​​trúc .NET mới được phát triển bởi Microsoft. Kiến trúc .NET là nỗ lực của Microsoft nhằm thiết kế lại các công cụ và công cụ phát triển phần mềm để giúp chúng thuận tiện hơn cho việc tạo các ứng dụng web. ADO.NET là sự phát triển mới của ADO, tập trung giải quyết các vấn đề liên quan đến việc phát triển hệ thống web và loại bỏ nhiều khuyết điểm của công nghệ ADO lỗi thời. Vấn đề với ADO là nó là công nghệ dựa trên COM. Đối với các ứng dụng một và hai tầng, COM là một nền tảng hoàn toàn có thể chấp nhận được, nhưng trong thế giới Web, việc sử dụng COM làm cơ chế truyền tải là điều gần như không thể. Có ba vấn đề chính với COM làm hạn chế việc sử dụng nó trên Web: thứ nhất, COM chỉ hoạt động trong môi trường Windows, thứ hai, việc truyền các tập bản ghi yêu cầu sắp xếp COM và thứ ba, các cuộc gọi COM không thể xuyên qua tường lửa của công ty. Công nghệ ADO.NET giải quyết cả ba vấn đề này thông qua việc sử dụng XML.
Một tính năng khác của ADO.NET là việc tách tập hợp bản ghi ADO truyền thống thành nhiều lớp riêng biệt. Thay vì giải quyết nhiều vấn đề, mỗi lớp được thiết kế để giải quyết một vấn đề cụ thể. Ví dụ: ADO.NET có lớp DataSetReader cung cấp quyền truy cập chỉ đọc vào dữ liệu ở chế độ Chỉ chuyển tiếp, với dữ liệu nằm ở phía máy chủ. Nhờ tất cả những hạn chế này, lớp này cung cấp khả năng đọc nhanh tập dữ liệu kết quả. Lớp DataTable hoạt động như một tập bản ghi bị vô hiệu hóa ở phía máy khách. Lớp DataRelation chia sẻ các tính năng chung với nhà cung cấp MSDataShape OLE DB. Trong mọi trường hợp, kiến ​​thức về công nghệ ADO truyền thống sẽ cực kỳ hữu ích khi học công nghệ ADO.NET mới.

Trong chương này, chúng ta đã xem xét công nghệ ADO (ActiveX Data Objects) và dbGo, một tập hợp các thành phần Delphi được thiết kế để truy cập các giao diện ADO. Bạn đã học cách làm việc với MDAC (Thành phần truy cập dữ liệu của Microsoft) và các cơ chế khác nhau để truy cập máy chủ cơ sở dữ liệu. Tôi đã nói với bạn về những ưu điểm và nhược điểm của công nghệ ADO.
Chương 16 giới thiệu kiến ​​trúc DataSnap tích hợp của Delphi, cho phép bạn phát triển các ứng dụng máy khách và máy chủ ba tầng. Tuy nhiên, vấn đề này có thể được giải quyết bằng ADO Cuốn sách này chủ yếu là về Delphi, vì vậy tôi sẽ kể cho bạn nghe về giải pháp cho vấn đề đó một cách tự nhiên đối với Môi trường Delphi. Sau khi xem xong DataSnap, chúng ta sẽ tiếp tục khám phá kiến ​​trúc dữ liệu tích hợp của Delphi. Trong Chương 17, chúng ta sẽ xem xét quá trình phát triển các thành phần dữ liệu của riêng bạn.

Sự kiện xảy ra trước khi lệnh được thực thi. Tùy chọn:
  • Nguồn là một chuỗi chứa câu lệnh SQL hoặc tên thủ tục được lưu trữ.
  • CursorType - loại con trỏ cho Recordset sẽ được mở. Loại con trỏ có thể được thay đổi. Những giá trị khả thi:
    • adOpenUnspecified(-1) - loại con trỏ không được chỉ định.
    • adOpenForwardOnly(0) - xác định con trỏ chỉ chuyển tiếp. Tương tự như con trỏ tĩnh nhưng bạn chỉ có thể cuộn tiếp qua các mục. Điều này tối ưu hóa việc thực thi nếu bạn chỉ phải thực hiện một lần chuyển qua Recordset.
    • adOpenKeyset(1) - Xác định con trỏ bộ khóa. Tương tự như con trỏ động, nhưng bạn không thể thấy các bản ghi được người dùng khác thêm vào, mặc dù các bản ghi do người dùng khác xóa không có sẵn trong Tập bản ghi của bạn.
    • adOpenDynamic(2) - Xác định con trỏ động. Những bổ sung, thay đổi và xóa của người dùng khác đều hiển thị; Tất cả các loại chuyển động thông qua Recordset đều được phép, ngoại trừ dấu trang nếu nhà cung cấp không hỗ trợ chúng.
    • adOpenStatic(3) - Xác định con trỏ tĩnh. Bản sao tĩnh của tập bản ghi mà bạn có thể sử dụng để tìm dữ liệu hoặc tạo báo cáo. Những bổ sung, thay đổi hoặc xóa của người dùng khác sẽ không hiển thị.
  • LockType - loại khóa cho Recordset sẽ được mở. Những giá trị khả thi:
    • adLockUnspecified(-1) - loại khóa không được chỉ định.
    • adLockReadOnly(1) - chỉ đọc. Bạn không thể thay đổi dữ liệu.
    • adLockPessimistic(2) - khóa bi quan. Nhà cung cấp đảm bảo chỉnh sửa hồ sơ thành công. Bản ghi bị chặn ngay sau khi bắt đầu chỉnh sửa và cho đến khi bản ghi được lưu.
    • adLockOptimistic(3) - khóa lạc quan. Nhà cung cấp chỉ khóa hồ sơ khi các thay đổi được lưu, tức là. khi bạn gọi phương thức Update().
    • adLockBatchOptimistic(4) - sửa đổi hàng loạt lạc quan. Cần thiết cho chế độ sửa đổi hàng loạt (lưu hồ sơ bị trì hoãn).
  • Tùy chọn - một số nguyên (dài) biểu thị các tùy chọn để thực hiện lệnh hoặc mở Recordset.
  • adStatus - xác định trạng thái sự kiện. Các giá trị có thể có - xem mô tả về tham số tương tự của sự kiện ConnectComplete.
  • pCommand là đối tượng Lệnh áp dụng sự kiện này.
  • pRecordset là đối tượng Recordset áp dụng sự kiện này.
  • pConnection là đối tượng Connection mà sự kiện này áp dụng.
Sự kiện WillExecute có thể xảy ra do các lệnh gọi tới Connection.Execute, Command.Execute hoặc Recordset.Open. Tham số pConnection luôn chứa tham chiếu đến đối tượng Connection. Nếu sự kiện xảy ra do lệnh gọi tới Connection.Execute, thì tham số pRecordset và pCommand sẽ được đặt thành Nothing. Nếu sự kiện xảy ra do lệnh gọi tới Recordset.Open, tham số pRecordset sẽ chứa tham chiếu đến đối tượng Recordset và tham số pCommand sẽ được đặt thành Nothing. Nếu sự kiện xảy ra do lệnh gọi Command.Execute, tham số pCommand sẽ chứa tham chiếu đến đối tượng Command và tham số pRecordset sẽ được đặt thành Nothing.

Khi bạn biết những điều cơ bản khi làm việc với ADO, bạn có thể chuyển sang viết chương trình để làm việc với ADO trong các ứng dụng. Chúng ta sẽ lại sử dụng ADO để kết nối với cơ sở dữ liệu Biblio.mdb, nhưng điều này là đủ cho phần trình diễn nguyên tắc chung. Hãy bắt đầu với ví dụ sau và sau đó chuyển sang lập trình:

1. Tạo một dự án mới bằng lệnh File > Dự án mới. Chọn biểu tượng EXE tiêu chuẩn trong hộp thoại Dự án mới và nhấp vào OK.

2. Đặt thuộc tính Tên của dự án thành ADORecordset.

3. Đặt thuộc tính Tên của Form1 thành frmMain và thuộc tính Caption thành Working with ADO Recordsets.

4. Tạo một danh sách trên biểu mẫu frmMain và đặt thuộc tính Tên của nó thành Tác giả thứ nhất.

Như đã đề cập trước đó, phần tử dữ liệu ADO là điều khiển ActiveX. Nó có thể được kéo vào biểu mẫu giống như bất kỳ phần tử nào khác. Các đối tượng Connection và Recordset là các DLL hoạt động (Thư viện liên kết động) và chỉ có thể được truy cập bằng cách tham chiếu đến thư viện kiểu.

GHI CHÚ Thư viện kiểu chứa mô tả đầy đủ về thành phần: thuộc tính, phương thức, sự kiện và kiểu dữ liệu.

5. Chạy lệnh Project trong Visual Basic > Tài liệu tham khảo để mở hộp thoại Tài liệu tham khảo.

8. Thêm các khai báo sau vào phần (Chung)(Tuyên bố) của biểu mẫu:

Riêng cn Như ADODB.Connection

Rs riêng tư dưới dạng ADODB.Recordset

9. Chèn đoạn mã sau vào thủ tục sự kiện Form_Load:

Biểu mẫu phụ riêng tư_Load()

Làm mờ cmd dưới dạng chuỗi

Làm mờ sql dưới dạng chuỗi

Dim cn As ADODB.Connection

Dim rs Như ADODB.Recordset

"Tạo chuỗi kết nối

cmd = "Nhà cung cấp=microsoft.jet.OLEDB.3.51"" & _

"Nguồn dữ liệu=" & _

"C:\Tệp chương trình\Microsoft Visual Studio" & _

"\VB98\Biblio.mdb"

"Thiết lập kết nối tới cơ sở dữ liệu

Đặt cn = ADODB.Connection mới

Chuỗi kết nối = cmd

"Tạo yêu cầu

sql = "chọn * từ tác giả"

"Mở tập bản ghi

Đặt rs.= ADODB.Recordset mới

Làm khi không rs.EOF


"Chuyển tới mục tiếp theo

"Đóng tập bản ghi.

Đặt rs = Không có gì

"Đóng kết nối

"hủy đối tượng kết nối

Đặt cn = Không có gì

10.Save và chạy dự án.

Chương trình chỉ cần truy cập cơ sở dữ liệu Biblio.mdb và điền tên các tác giả từ bảng Tác giả vào danh sách. Bạn có thể sẽ nghĩ rằng chương trình quá lớn cho một tác vụ đơn giản như vậy, nhưng nếu xem xét kỹ, bạn sẽ hiểu rằng không có gì phức tạp trong đó.

Khi bắt đầu chương trình, hai biến được khai báo là cmd và sql. Biến cmd sẽ lưu trữ chuỗi kết nối ADO dùng để kết nối tới cơ sở dữ liệu. Biến sql dành cho văn bản của truy vấn SQL. Đoạn sau tạo một dòng để kết nối với Biblio.mdb bằng cách sử dụng nhà cung cấp OLEDB mới (được chỉ định sau cấu trúc Provider = ở đầu dòng). Nếu bạn cần kết nối với một loại nguồn dữ liệu khác, chẳng hạn như SQL Server, chỉ định một nhà cung cấp khác. Tham số chuỗi thứ hai chỉ định tên của cơ sở dữ liệu. Chuỗi kết nối ADO thực hiện tất cả các công việc nặng nhọc nên đây phải là trọng tâm chính của bạn. Làm nổi bật mã này trong chức năng riêng biệt cho phép bạn tạo nhiều loại dây khác nhau kết nối để làm việc với các cơ sở dữ liệu khác nhau (ví dụ: Access, SQL Server và Oracle). Bạn có thể truyền tham số cho hàm như vậy, hàm này được sử dụng để xây dựng một chuỗi kết nối duy nhất. Điều này sẽ đơn giản hóa quá trình di chuyển các ứng dụng hỗ trợ ADO của bạn sang các nguồn dữ liệu khác.

Bước tiếp theo- kết nối thực tế với cơ sở dữ liệu. Để thực hiện việc này, chúng ta tạo một đối tượng ADO.Connection rồi đặt thuộc tính ConnectionString của nó thành cmd. Sau đó phương thức này được thực thi. Mở đối tượng này. Phương thức này lấy dữ liệu tìm thấy trong thuộc tính ConnectionString và sử dụng nó để kết nối với cơ sở dữ liệu.

Sau khi thiết lập kết nối tới cơ sở dữ liệu, chúng ta mở đối tượng ADO. Recordset để nhận hồ sơ. Tuy nhiên, trước tiên bạn phải chuyển cho nó một truy vấn SQL để xác định các bản ghi bạn muốn. Trong chương trình của chúng tôi, dòng sau đây thực hiện điều này:

sql = "chọn * từ tác giả"

Không đi sâu vào chi tiết SQL, ý nghĩa của truy vấn này là: “chọn tất cả các bản ghi (*) từ bảng có tên Tác giả”. Đây chính xác là những gì đã được thực hiện trong ví dụ của chúng tôi.

Chúng tôi có một truy vấn có thể được sử dụng để tạo một tập hợp các bản ghi. Một đối tượng recordset mới được tạo như sau:

Đặt rs = ADODB.Recordset mới

Bộ mới được tạo không chứa bất kỳ thông tin nào. Trong khối With, chúng ta yêu cầu ADO mở tập hợp bằng lệnh

Mở sql, cn, adOpenForwardOnly, adLockReadOnly

Có thể bạn đã nhận thấy các tham số cần thiết để mở một tập bản ghi. Tham số đầu tiên lưu trữ truy vấn SQL cho bộ này. Tham số thứ hai, cn, chỉ định rằng tập hợp sẽ sử dụng đối tượng kết nối cn để kết nối với cơ sở dữ liệu. Có thể rút ra một sự tương tự giữa một tập hợp các bản ghi và một máy: kết nối là con đường mà máy đi đến dữ liệu. Tham số tiếp theo cho ADO biết loại con trỏ cơ sở dữ liệu nào sẽ được sử dụng cho tập hợp. Bảng liệt kê sau đây những lựa chọn khả thi con trỏ với những mô tả ngắn gọn.

Kiểu con trỏ Sự miêu tả
chỉ quảng cáoOpenForward Con trỏ kiểu này chỉ có thể được sử dụng để lặp tuần tự qua các bản ghi theo một hướng. Tìm kiếm ở hướng ngược lại và chuyển đổi tùy ý không được phép. Tuy nhiên, tùy chọn này nhanh và hữu ích nếu bạn cần điền nhanh vào danh sách hoặc hộp tổ hợp
Bộ khóa Ad0pen Loại con trỏ tối ưu cho các bộ lớn. Bạn không nhận được thông báo về những thay đổi dữ liệu có thể ảnh hưởng đến tập bản ghi của bạn
Ad0penĐộng Con trỏ cho phép bạn theo dõi tất cả những thay đổi mà người dùng khác thực hiện đối với tập bản ghi của bạn. Nó có nhiều khả năng nhất, nhưng vì điều này mà nó hoạt động chậm hơn tất cả những khả năng khác
Quảng cáoMởTĩnh Con trỏ tĩnh rất hữu ích cho các tập hợp nhỏ

Cuối cùng, tham số cuối cùng cho ADO biết rằng tập bản ghi sẽ ở chế độ chỉ đọc. Thay vào đó, bạn có thể chỉ định một pe-zimlock khác từ bảng sau, tuy nhiên, trong ví dụ của chúng tôi, tùy chọn nhanh nhất đã được chọn.

Nếu tất cả tham số được chỉ định chính xác, tập bản ghi sẽ mở ra và bạn có thể làm việc với dữ liệu của nó.

Trong đoạn mã sau, chương trình sẽ lặp qua tất cả các bản ghi cho đến khi tìm thấy cờ kết thúc tệp (EOF). Khi di chuyển con trỏ tới bản ghi tiếp theo, chúng ta nhập dữ liệu từ trường Tác giả vào danh sách:

lstAuthors.AddItem rs("Tác giả")

Sau khi thêm tên tiếp theo vào danh sách, chúng ta chuyển sang mục tiếp theo bằng phương thức. Di chuyểnTiếp theo. Nếu bạn quên điều này, vòng lặp sẽ chạy mãi mãi vì sẽ không bao giờ đạt đến cuối tập tin. Cuối cùng, sau khi hoàn thành công việc, mọi thứ mở đều phải đóng lại, mọi thứ được tạo ra đều phải bị hủy. Để thực hiện điều này, hãy gọi phương thức .Close trên các đối tượng Recordset và Connection. Sau đó, các đối tượng này được gán Nothing để ngăn chặn rò rỉ bộ nhớ trong ứng dụng của bạn.

CHÚ Ý Khi xử lý các mục nhập tập hợp trong một vòng lặp, hãy đảm bảo đưa một phương thức vào vòng lặp. Di chuyểnTiếp theo. Nếu bạn quên làm điều này (và điều này xảy ra thường xuyên), chương trình của bạn sẽ rơi vào vòng lặp. Viết câu lệnh Do While..., sau đó là lệnh .MoveNext ngay trước lệnh Loop, sau đó chỉ chèn mã xử lý dữ liệu của bạn. Bằng cách này, bạn giảm khả năng xảy ra lỗi xuống mức tối thiểu.

Thêm mục

Mặc dù tính năng này không bắt buộc trong ví dụ này nhưng hầu hết các ứng dụng đều thêm bản ghi mới vào tập hợp. Với các đối tượng ADO Recordset, công việc này cực kỳ dễ dàng. Để thực hiện việc này, chương trình nên gọi phương thức.AddNew:

rs("Tác giả) = "Doe, John" rs("Au_ID") = 123456

Mọi thứ đều rất đơn giản. Khi bạn cần tạo một mục mới, bạn gọi phương thức .AddNew. Nó tạo ra một bản ghi trống, sau đó chứa đầy dữ liệu. Điều này có thể được thực hiện theo nhiều cách, bao gồm những cách sau:

Rs("Tác giả") = "Doe, John"

Rs!Tác giả = "Doe, John"

Rs.Fields(1) = "Doe, John"

Tất cả đều tương đương nhau và sự lựa chọn phụ thuộc vào sở thích cá nhân của bạn. Cá nhân tôi thích phương pháp đầu tiên hơn vì nó trông rõ ràng nhất. Tôi biết chính xác trường nào đang được cập nhật và vì tên trường nằm trong dấu ngoặc kép nên nó có thể chứa dấu cách.

Sau khi nhập dữ liệu vào bản ghi, bạn nên cập nhật tập hợp bằng cách gọi phương thức. Cập nhật.

Cập nhật hồ sơ

Quá trình cập nhật bản ghi cũng tương tự như quá trình thêm, nhưng lần này bạn không phải gọi phương thức .AddNew. Chỉ cần di chuyển con trỏ cơ sở dữ liệu đến bản ghi mong muốn, thay đổi dữ liệu và gọi phương thức là đủ. Cập nhật. Ví dụ:

Rs("Tác giả") = "Brown, Steve"

Rs("Au_ID") = 373737

GHI CHÚ Nếu bạn đã từng làm việc với các đối tượng DAO, bạn có thể quen với việc gọi một phương thức. Edit để chuyển sang chỉnh sửa dữ liệu. Nó không được hỗ trợ bởi các đối tượng ADO.

Xóa mục nhập

Xóa bản ghi cũng dễ dàng như vậy trong ADO. Tất cả những gì bạn phải làm là đặt con trỏ cơ sở dữ liệu trên bản ghi cần xóa và gọi phương thức. Xóa bỏ. Chương trình trông giống như thế này:

"Tạo yêu cầu

sql = "chọn *từ tác giả trong đó = "Brown, Steve""

"Mở tập bản ghi

Đặt rs = ADODB.Recordset mới

Mở sql, cn, adOpenForwardOnly, adLockReadOnly

Nếu rs.RecordCount > 0 thì

" Đóng tập bản ghi

" Phá hủy một đối tượng recordset

Đặt rs = Không có gì

manh mối Chuyển sang sử dụng ADO vì Microsoft đang phát triển công nghệ dữ liệu của mình theo hướng này. Bạn không chỉ được làm việc với công nghệ mới nhất mà còn có thể chuyển ứng dụng của mình sang các nguồn dữ liệu khác với những thay đổi mã tối thiểu (hoặc không có). Hơn nữa, ADO thậm chí còn cho phép bạn trao đổi dữ liệu giữa cơ sở dữ liệu và Web. trang!

Bây giờ bạn đã biết cách tạo cơ sở dữ liệu Access và làm việc với chúng theo nhiều cách khác nhau. Các kỹ năng được đề cập trong bài học này sẽ giúp bạn làm việc với cơ sở dữ liệu trong các ứng dụng trong tương lai. Mặc dù khả năng của phiên bản mới của Trình quản lý dữ liệu trực quan đã tăng lên đáng kể nhưng tôi vẫn khuyên bạn nên mua Microsoft Access nếu bạn chưa từng làm như vậy trước đây. Access có nhiều tính năng giúp việc tạo cơ sở dữ liệu dễ dàng hơn cả quy trình đơn giản được mô tả ở trên. Điều tuyệt vời nhất là cơ sở dữ liệu của bạn sẽ vẫn tương thích với Visual Basic!

Sau khi tìm hiểu cách làm việc với các tệp và cơ sở dữ liệu, bạn có thể lấy dữ liệu từ ứng dụng của mình và lưu nó để tải xuống hoặc in sau này, đồng thời sử dụng dữ liệu đó để lưu và truy xuất các tham số vận hành ứng dụng. Hãy dành thời gian để thử nghiệm với Trình quản lý dữ liệu trực quan. Nó có nhiều tính năng chưa được đề cập trong hướng dẫn này (để mô tả đầy đủ sẽ cần một cuốn sách riêng). Bằng cách kết hợp khả năng lập trình và cơ sở dữ liệu của Visual Basic, bạn có thể tạo ra các ứng dụng mạnh mẽ. Bài học tiếp theo tập trung vào khía cạnh quan trọng thứ ba của bất kỳ ứng dụng nào - in ấn.

Chú thích: Trong bài giảng này, chúng ta sẽ nói về cơ chế truy cập dữ liệu BDE và ADO cũng như thảo luận về ưu và nhược điểm của chúng. Hãy tạo cơ sở dữ liệu bằng MS Access. Sau đó, chúng ta sẽ tạo một ứng dụng hoạt động với cơ sở dữ liệu này bằng cơ chế ADO.

Kể từ khi công nghệ cơ sở dữ liệu ra đời, các lập trình viên cần có cơ chế để truy cập chính dữ liệu này. Nhiều công ty khác nhau theo cách riêng của họ, họ đã cố gắng cung cấp cho họ một cơ hội như vậy. Ví dụ: để làm việc với các bảng loại dBase, Hệ thống quản lý cơ sở dữ liệu ( cơ sở dữ liệu) Máy cắt tóc. Đối với thời đại của hệ điều hành, MS-DOS là một giải pháp tuyệt vời. Tuy nhiên Máy cắt tóc không thể làm việc với bất kỳ loại bảng nào khác. Và càng xuất hiện nhiều loại dữ liệu thì nhu cầu phát triển một công cụ truy cập phổ quát có thể hoạt động với bất kỳ loại dữ liệu nào càng trở nên cấp thiết hơn.

Cơ chế truy cập dữ liệu là một công cụ phần mềm cho phép bạn truy cập cơ sở dữ liệu và các bảng của nó. Theo quy định, đây là trình điều khiển ở dạng tệp *.dll, được cài đặt trên PC của nhà phát triển (và của khách hàng) và được chương trình sử dụng để giao tiếp với cơ sở dữ liệu.

So sánh BDE và ADO

Công cụ cơ sở dữ liệu Borland (BDE)- sự phát triển đầu tiên như vậy từ Borland. Cái này cơ chế truy cập dữ liệu cho phép truy cập vào các định dạng cơ sở dữ liệu máy chủ tệp và cục bộ dBase, FoxPro và Paradox, tới nhiều định dạng khác nhau máy chủ SQL và nhiều nguồn dữ liệu khác, quyền truy cập được hỗ trợ bằng trình điều khiển ODBC. Ví dụ, sử dụng BDE Bạn có thể làm việc trực tiếp với các tệp bảng tính MS Excel. Than ôi, cơ chế truy cập BDE thậm chí bị chính Borland coi là lỗi thời. TRONG khoảnh khắc này Nhiều công cụ Delphi có tính đa nền tảng, nghĩa là các chương trình có sửa đổi nhỏ có thể được chuyển sang các hệ điều hành khác. Tập đoàn Borland vừa cho ra mắt môi trường phát triển phần mềm nhanh chóng mới - Kylix, tạo ra các ứng dụng cho hệ điều hành Gia đình Linux. Người ta thường nói Kylix là Delphi cho Linux. Đúng vậy - nếu bạn có thể lập trình ở Delphi, bạn cũng có thể lập trình ở Kylix. Hầu hết các công cụ của Delphi đều được kế thừa từ Kylix, nhưng than ôi, không phải vậy. BDE. Phát triển hơn nữa cái này cơ chế truy cập dữ liệuđã bị ngừng sản xuất bởi Tập đoàn Borland.

Tuy nhiên, còn quá sớm để chôn cất anh ta. Nhiều lập trình viên vẫn sử dụng công cụ này để phát triển ứng dụng cho các công ty nhỏ. Tôi có thể nói gì đây, công ty Huawei của Trung Quốc, công ty phát triển các tổng đài điện tử mới nhất cho cả điện thoại cố định và di động, vẫn sử dụng BDEđể truy cập cài đặt và số liệu thống kê của các PBX này! Bên cạnh đó, BDE có nhiều tính năng đơn giản và tiện lợi cho người lập trình như tạo bảng theo chương trình.

Dễ sử dụng BDE Rất khó để đánh giá quá cao nhưng không thể không nhắc đến những nhược điểm. Nhược điểm chính là sự phân phối của các ứng dụng. Nếu ứng dụng của bạn sử dụng các thành phần để truy cập dữ liệu BDE, thì khách hàng sẽ sử dụng chương trình của bạn phải cài đặt nó BDE. Hơn nữa, nếu bạn đã sử dụng bí danh (bí danh cơ sở dữ liệu) thì máy khách cũng phải được cấu hình cho các bí danh tương tự. Tuy nhiên, việc tạo gói cài đặt bằng tiện ích Cài đặt tiêu chuẩn Khiên Express loại bỏ vấn đề này. Tiện ích này cho phép bạn kích hoạt cơ chế được cấu hình BDE có trong gói cài đặt chương trình của bạn. Tất nhiên, bạn phải trả tiền cho việc này bằng kích thước tệp cài đặt lớn.

Một nhược điểm khác không chỉ liên quan đến BDE, mà còn bất kỳ phổ quát nào khác cơ chế truy cập dữ liệu. Tính phổ quát của một cơ chế như vậy hàm ý sự phức tạp trong việc thực hiện nó. Lập trình viên được cung cấp một công cụ làm sẵn rất thuận tiện khi làm việc, nhưng công cụ này khá “nặng” - khi sử dụng nó, bạn sẽ tăng kích thước ứng dụng của mình lên khá đáng kể.

Trong khóa học trước "Giới thiệu về lập trình ở Delphi", chúng ta đã đề cập đến cách làm việc với cơ sở dữ liệu bằng cách sử dụng BDE. Chúng tôi sẽ không quay lại những chủ đề này nữa, mặc dù thỉnh thoảng chúng tôi sẽ đề cập đến BDEđể chứng minh những khả năng nhất định không có trong các cơ chế truy cập dữ liệu khác hoặc khác với chúng. Do đó, nếu bạn bỏ lỡ khóa học này, thì ít nhất hãy xem lại công việc một cách ngắn gọn với BDE trong bài giảng 29-32.

Đối tượng dữ liệu ActiveX (ADO)- Cái này cơ chế truy cập dữ liệu, được phát triển bởi Tập đoàn Microsoft. Nói chính xác hơn thì ADO- đây là một tiện ích bổ sung cho công nghệ OLE DB, thông qua đó bạn có thể giao tiếp với nhiều dữ liệu ứng dụng khác nhau của Microsoft. Vào giữa những năm 1990, công nghệ phát triển vượt bậc COM và do đó Tập đoàn Microsoft đã công bố chuyển đổi dần dần từ công nghệ cũ ODBCđến một cái mới OLE DB. Tuy nhiên, công nghệ OLE DB khá phức tạp, việc sử dụng công nghệ này diễn ra ở cấp độ hệ thống và đòi hỏi nhiều kiến ​​thức cũng như công sức của người lập trình. Ngoài ra, công nghệ OLE DB rất nhạy cảm với lỗi và gặp sự cố ngay từ cơ hội đầu tiên. Để giúp cuộc sống của các lập trình viên trở nên dễ dàng hơn, Microsoft đã phát triển một tiện ích bổ sung lớp ứng dụng ADO mà chúng ta sẽ học trong khóa học này.

Theo khả năng của bạn ADO nhắc nhở BDE, mặc dù tất nhiên là nhiều hơn công cụ đắc lực. Borland đã phát triển một bộ các thành phần để truy cập ADO và ban đầu gọi nó là ADOExpress. Tuy nhiên, Tập đoàn Microsoft kiên quyết phản đối việc sử dụng tên gọi của mình trong các sản phẩm của bên thứ ba, do đó, bắt đầu từ Delphi 6, bộ thành phần này bắt đầu được gọi là dbGo. Bạn có thể thấy các thành phần này trên tab ADO bảng thành phần.

Công nghệ ADO, cũng như BDE, độc lập với một máy chủ cơ sở dữ liệu cụ thể, có hỗ trợ cho cả cơ sở dữ liệu cục bộ thuộc nhiều loại khác nhau và một số cơ sở dữ liệu máy khách-máy chủ. Công nghệ này có nhiều ưu điểm. Trình điều khiển do Microsoft phát triển để sử dụng riêng có độ tin cậy cao hơn trình điều khiển nhà sản xuất bên thứ ba. Vì vậy, nếu bạn cần làm việc với cơ sở dữ liệu Truy cập MS hoặc đối với kiến ​​trúc máy khách-máy chủ, hãy sử dụng MS SQL Server, sau đó sử dụng ADO sẽ được ưu tiên nhất. Ngoài ra, có một điểm cộng trong vấn đề phân phối chương trình - tất cả các Windows hiện đại đều có trình điều khiển tích hợp sẵn ADO. Nói cách khác, chương trình của bạn sẽ chạy trên bất kỳ PC nào có cài đặt Windows.

Điều kỳ lạ là nhược điểm chính còn nằm ở vấn đề phân phối chương trình. Microsoft đang làm điều gì đó khá thông minh. Cứ sau vài năm, các phiên bản Windows mới lại xuất hiện. Người dùng bình thường thường không cần phải chuyển sang hệ điều hành mới, đặc biệt là khi mỗi hệ thống mới ngày càng đòi hỏi nhiều hơn về tài nguyên PC. Để buộc người dùng phải truy cập phiên bản mới, Microsoft chắc chắn sẽ giới thiệu một số tiêu chuẩn hoặc công nghệ mới không tương thích với các tiêu chuẩn hoặc công nghệ cũ. Và đối với các phiên bản cũ hơn, không có cải tiến nào được cung cấp. Vì vậy, người dùng tội nghiệp phải nghiến răng chịu đựng và chi tiền cho các phiên bản mới của hệ điều hành và gói MS Office. Vì vậy, khi sử dụng công nghệ ADO bạn phải suy nghĩ xem bạn có phiên bản Windows nào người dùng cuối liệu chương trình của bạn có hoạt động trên PC của anh ấy hay không.

Công nghệ ADO thực sự là một phần Cấu phần truy cập dữ liệu của Microsoft (MDAC). Microsoft phân phối MDAC như một sản phẩm riêng biệt, may mắn thay là miễn phí. Tuy nhiên, chỉ có phiên bản mới nhất được hỗ trợ MDAC. Ví dụ: Delphi 7 bao gồm MDAC 2.6. Khi phân phối các chương trình của riêng bạn, bạn nên tính đến việc rất có thể khách hàng đã cài đặt phần mềm tương tự này. MDAC, và hầu hết phiên bản mới nhất. Tuy nhiên, nếu anh ta sử dụng các phiên bản Windows cũ hơn (Win95, 98, ME, NT), thì bạn sẽ cần phải quan tâm đến việc cài đặt MDAC tới máy tính của anh ấy. Nếu anh ta đã cài đặt Win2000, WinXP hoặc hệ điều hành mới hơn thì MDAC anh ấy đã có nó rồi và bạn không có gì phải lo lắng cả.

Một điểm trừ nghiêm trọng khác ADO Vấn đề là nó sử dụng công nghệ COM khá chậm để kết nối với cơ sở dữ liệu. Nếu cơ sở dữ liệu của bạn chứa hàng nghìn bản ghi thì tốc độ làm việc với bảng có thể chậm hơn hàng trăm lần so với khi bạn sử dụng BDE! Trên các PC hiện đại có tần số bộ xử lý lên tới 2 GHz trở lên, những sự chậm lại này có thể không đáng chú ý, nhưng khi làm việc với căn cứ khổng lồ dữ liệu trên các PC chậm hơn sẽ chuyển sang trạng thái chờ hoàn toàn.

Các thành phần chính mà chúng ta phải làm việc là TADOConnection (để kết nối với cơ sở dữ liệu), TADOTable (analog Bảng TT từ BDE), TADOQuery (tương tự truy vấn từ BDE, để thực hiện truy vấn và truy xuất tập dữ liệu) và TADODataSet (dành cho tập dữ liệu thu được thông qua truy vấn SQL).

Tạo cơ sở dữ liệu MS Access

Cơ sở dữ liệu Truy cập MS có nhiều ưu điểm nên các lập trình viên thường thích sử dụng chúng. Đầu tiên, cơ sở dữ liệu Truy cập MS- đây là một tập tin. Cho dù nó chứa bao nhiêu bảng và chỉ mục, tất cả đều được lưu trữ trong một tệp duy nhất. Điều này có nghĩa là cơ sở dữ liệu như vậy dễ bảo trì hơn - chuyển đến vị trí mới, tạo bản sao lưu và như thế. Một điểm cộng nữa là tên trường trong cơ sở dữ liệu như vậy có thể được viết bằng chữ cái tiếng Nga.

Cách tốt nhất để học tài liệu mới là thông qua thực hành. Ví dụ: hãy tạo cơ sở dữ liệu cho bộ phận nhân sự của một doanh nghiệp nào đó. Chúng tôi cần dữ liệu nhân viên nào? Trước hết, họ, tên và chữ viết tắt. Sau đó cho biết giới tính (nam hay nữ), Tình trạng gia đình(độc thân hoặc đã kết hôn), số con. Bạn cũng sẽ cần ngày sinh và ngày nhập cảnh để làm việc. Kinh nghiệm làm việc trong nhiều năm. Giáo dục. Nhập ngũ hay không. Số điện thoại nơi bạn có thể liên hệ với nhân viên bất cứ lúc nào. Vị trí và bộ phận của nhân viên (nếu có) mà anh ta đã đăng ký. Và cả địa chỉ nhà của anh ấy nữa. Đồng thời, chúng tôi tính đến việc nhân viên không nhất thiết phải là cư dân của thành phố nơi anh ta làm việc. Điều gì sẽ xảy ra nếu anh ấy đến làm việc từ thành phố khác? Hoặc thậm chí từ một quốc gia khác? Do đó, bạn sẽ phải nhập cả quốc gia và thành phố - chẳng hạn nếu bạn cần lập báo cáo về nhân viên đã đăng ký ở Ukraine thì sao? Đó là lượng dữ liệu cần nhập cho bộ phận nhân sự! Nhưng chúng tôi đã đơn giản hóa chúng hơn một chút. Kinh nghiệm làm việc được chia thành chung và liên tục. Dữ liệu này được tính đến khi tính thời gian nghỉ ốm. Nhưng đối với cơ sở dữ liệu huấn luyện, những chi tiết như vậy có thể bị bỏ qua.

Vì vậy, trước hết, chúng tôi tối ưu hóa dữ liệu dựa trên quy tắc ba dạng bình thường. Kết quả là chúng ta có được bốn bảng:


Cơm. 2.1.

Bảng chính ở đây sẽ là LichData, chứa dữ liệu cơ bản về nhân viên. Nó có kết nối quan hệ với các bảng khác. Trường "Khóa" sẽ tự động tăng, nghĩa là nó sẽ tự động được thêm một trường, đảm bảo cho chúng tôi tính duy nhất của khóa. TRONG bảng phụ có toàn bộ trường "Nhân viên" sẽ được sử dụng để cung cấp thông tin liên lạc. Hơn nữa, các lĩnh vực quan trọng trong bảng con sẽ không được.

Bảng chính duy trì mối quan hệ một đối một với Doljnost và Địa chỉ và mối quan hệ một-nhiều với bảng Điện thoại, bởi vì nhân viên có thể có cả điện thoại nhà và điện thoại cơ quan, và có thể có một vài chiếc điện thoại di động trong túi. Tức là một nhân viên có thể có nhiều điện thoại.

Bây giờ chúng ta đã quyết định xong các trường và kết nối, đã đến lúc tạo cơ sở dữ liệu. Để làm điều này, hãy tải xuống chương trình Truy cập MS.

Nếu bạn không có bảng "Tạo tệp" ở bên phải cửa sổ, hãy chọn lệnh "Tệp - Mới". Sau đó chọn lệnh Cơ sở dữ liệu mới. Một dấu nhắc sẽ xuất hiện ngay lập tức với tên của cơ sở dữ liệu này. Tạo một thư mục mà chúng tôi vẫn cần cho dự án mới, chỉ định thư mục này và đặt tên cho cơ sở dữ liệu là ok (bộ phận nhân sự). Khi bạn nhấp vào nút "Tạo", cửa sổ cơ sở dữ liệu này sẽ xuất hiện:


Cơm. 2.2.

Bây giờ chúng ta cần tạo bốn bảng. Do đó, hãy nhấp đúp vào lệnh “Tạo bảng ở chế độ thiết kế” và đi tới trình thiết kế. Ở phía bên trái, chúng tôi nhập tên của trường và bằng các chữ cái tiếng Nga. Trong trường "Loại dữ liệu", hãy chọn loại và trên tab "Chung", thực hiện cài đặt trường. Mô tả trường là tùy chọn. Vì vậy, hãy tạo các trường:

  1. "Chìa khóa". Tất nhiên, chúng tôi viết tên trường không có dấu ngoặc kép. Chúng ta chọn kiểu dữ liệu “Counter”, đây là kiểu dữ liệu tăng tự động. Trong cài đặt, đảm bảo rằng trường được lập chỉ mục - Có (Không được phép trùng hợp ngẫu nhiên). Bấm chuột phải vào trường này và chọn Trường khóa. Một biểu tượng phím sẽ xuất hiện ở bên trái của trường.
  2. "Họ". Loại trường là văn bản, kích thước 25 ký tự. Trường được lập chỉ mục - Có (cho phép khớp). Rốt cuộc, người thân hoặc người trùng tên có thể bị bắt!
  3. "Tên". Loại trường là văn bản, kích thước 25 ký tự. Trường được lập chỉ mục - Có (cho phép khớp).
  4. "Họ". Loại trường là văn bản, kích thước 25 ký tự. Không cần chỉ mục.
  5. "Sàn nhà". Văn bản, kích thước 3 ký tự. Trong định dạng trường, tất nhiên chỉ rõ "chồng/vợ" mà không có dấu ngoặc kép.
  6. "Sem_Pozh". Kiểu Boolean, định dạng trường "Có/Không". Ở đây chúng tôi sẽ cho biết liệu nhân viên đã kết hôn hay chưa.
  7. "Những đứa trẻ." Kiểu số, kích thước trường Byte (thật khó để tưởng tượng rằng ai đó sẽ có hơn 255 con!).
  8. "Ngày sinh". Loại trường - Ngày/Giờ. Chọn định dạng Ngày ngắn. Sau đó chọn định dạng tương tự cho trường Mặt nạ. Khi bạn cố gắng chọn mặt nạ, bạn sẽ được yêu cầu xác nhận việc lưu bảng. Trả lời khẳng định và thay vì tên bảng mặc định “Bảng 1”, hãy nhập “LichData”, đây sẽ là tên của bảng đầu tiên của chúng ta. Sau đó, cửa sổ tạo mặt nạ đầu vào sẽ xuất hiện. Chọn "Định dạng ngày ngắn", nhấp vào "Tiếp theo", sau đó nhập "00.00.0000" trong cửa sổ "Mặt nạ nhập". Kết quả chúng ta sẽ có một mặt nạ có dạng “dd.mm.yyyy”.
  9. "Ngày_Đăng". Mọi thứ vẫn giống như ở số 8.
  10. "Kinh nghiệm". Loại trường là số, kích thước là byte.
  11. "Giáo dục". Văn bản, kích thước trường 30 ký tự. Rốt cuộc, ở đây có thể có một đoạn văn bản dài, chẳng hạn như “giáo dục kỹ thuật đại học chưa hoàn thành”.
  12. "đi lính" Kiểu Boolean, định dạng Có/Không.

Kết quả là chúng ta có được hình ảnh sau đây.

Lỗi

Đối tượng ADO.Connection, kết nối với cơ sở dữ liệu từ VBScript, thuộc tính ConnectionString, tạo chuỗi kết nối OLE DB bằng tệp UDL, xử lý lỗi khi kết nối với cơ sở dữ liệu, Thu thập lỗi

Việc tạo một đối tượng Connection rất đơn giản. Ví dụ: để kết nối với cơ sở dữ liệu Northwind trên Máy chủ SQL có tên LONDON, bạn có thể sử dụng mã như

mờ cn

cn.Provider = "SQLOLEDB"

& "Ban đầuMục lục= Gió Bắc"

cn.Mở

Về nguyên tắc, điều này là khá đủ để tạo một đối tượng kết nối hoạt động (ví dụ, để xác minh điều này, bạn có thể chạy lệnh kịch bản.Echocn.Tình trạng trước và sau khi mở). Tuy nhiên, sẽ rất hợp lý nếu nói chi tiết hơn về các thuộc tính và phương thức khác nhau của đối tượng này.

tài sản Các nhà cung cấp xác định trình điều khiển sẽ được sử dụng để kết nối với cơ sở dữ liệu. Có hai loại trình điều khiển kết nối thường được sử dụng - trình điều khiển OLE DB và ODBC. Nếu có thể, bạn nên sử dụng kết nối OLE DB - một phương pháp hiện đại hơn và hoạt động nhanh hơn nhiều. Thuộc tính Nhà cung cấp chỉ phải được chỉ định khi kết nối qua OLE DB; khi kết nối qua ODBC, tất cả các tham số cần thiết đều được chuyển bằng thuộc tính ConnectionString. Giá trị thuộc tính của nhà cung cấp để kết nối với các nguồn dữ liệu khác nhau có thể trông như thế này:

o "Microsoft .Jet .OLEDB .4.0" - để kết nối với các tệp Access và Excel cũng như các nguồn dữ liệu dựa trên Jet khác;

o "SQLOLEDB" - để kết nối với SQL Server (như trong ví dụ)

o "MSDAORA .1" - để kết nối với máy chủ Oracle;

o "ADsDSOObject" - để kết nối với cơ sở dữ liệu Windows Directory Service.

tài sản Chuỗi kết nối- thuộc tính chính của đối tượng Connection. Nó xác định các tham số để kết nối với nguồn (giá trị của nó là một tập hợp các tham số được phân tách bằng dấu chấm phẩy, thứ tự ý nghĩa của chúng không quan trọng). Trong ví dụ của chúng tôi, chúng tôi đã chuyển bốn giá trị tham số - ID người dùng - ID người dùng (điều này có nghĩa là chúng tôi đang sử dụng kết nối Máy chủ SQL), Mật khẩu - mật khẩu và Nguồn dữ liệu - tên của máy chủ cơ sở dữ liệu, Danh mục ban đầu - tên của cơ sở dữ liệu trên máy chủ này. Để truyền ConnectionString, bạn cũng có thể sử dụng phương thức Mở. Nếu chúng tôi đang sử dụng kết nối Windows với SQL Server, mã kết nối có thể trông như thế này:

mờ cn

Đặt cn = CreateObject("ADODB.Connection")

cn.Open "Nhà cung cấp=SQLOLEDB;Bảo mật tích hợp=SSPI;Thông tin bảo mật liên tục=False;Danh mục ban đầu=Northwind;Nguồn dữ liệu=london1"

Khi kết nối với tệp Access hoặc Excel, chuỗi kết nối có thể trông như thế này:

cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Nguồn dữ liệu=D:\Borey.mdb"

Cách dễ nhất để tạo chuỗi kết nối là sử dụng tệp UDL. Để thực hiện việc này, bạn cần tạo một tệp văn bản thông thường, đổi tên nó sao cho phần mở rộng của nó trông giống như .udl (từ liên kết dữ liệu người dùng), nhấp đúp và định cấu hình các tham số kết nối. Sau đó, bạn có thể mở tệp này trong Notepad và sao chép dòng đã tạo. Bạn cũng có thể sử dụng liên kết tới tệp UDL đã tạo trong chuỗi kết nối:

cn.ConnectionString = "Tên tệp = d:\mylink.udl"

Phương pháp này được khuyên dùng nhiều hơn (đặc biệt nếu các tệp UDL nằm trong thư mục mạng chỉ đọc ẩn) vì nó cho phép thực hiện các thay đổi tập trung trên tất cả các ứng dụng nếu nguồn dữ liệu chuyển sang máy chủ khác.

Để kết nối qua ODBC, trước tiên bạn nên tạo nguồn dữ liệu ODBC (thông qua Bảng điều khiển -> Nguồn dữ liệu (ODBC), sau đó tạo chuỗi kết nối theo cách tương tự bằng cách sử dụng tệp UDL, chọn Nhà cung cấp Microsoft OLE DB cho ODBC Tài xế lái xe.

· phương pháp Mở cho phép bạn mở kết nối tới cơ sở dữ liệu (và kiểm tra chức năng của nó). Nó có thể lấy chuỗi kết nối, tên người dùng và mật khẩu làm tham số.

· phương pháp Đóng cho phép bạn đóng kết nối (đối tượng kết nối không bị xóa khỏi bộ nhớ). Để loại bỏ hoàn toàn đối tượng này, bạn có thể sử dụng mã

cn.Đóng

Đặt cn = Không có gì

hoặc đơn giản Bộcn= Không có gì - kết nối sẽ tự động bị ngắt.

Có nhiều thuộc tính và phương thức khác có sẵn cho đối tượng này nhưng chúng sẽ không được đề cập ở đây (xem tài liệu hoặc các khóa đào tạo của Microsoft để biết thêm thông tin). Thuộc tính duy nhất bạn thực sự cần xem xét là thuộc tính Errors, thuộc tính này trả về một tập hợp các đối tượng Error. Lỗi khi thiết lập hoặc vận hành kết nối xảy ra rất thường xuyên (nhập sai mật khẩu hoặc tên người dùng, người dùng không có đủ quyền kết nối, không thể truy cập vào máy tính qua mạng, v.v.) nên rất nghiêm trọng. đề nghị thực hiện xử lý lỗi trong chương trình. Cách đơn giản nhất để triển khai trình xử lý lỗi có thể giống như sau:

Lờ mờcn

Đặt cn = CreateObject("ADODB.Connection")

cn.Provider = "SQLOLEDB"

cn.ConnectionString = "ID người dùng=SA;Mật khẩu=mật khẩu;Nguồn dữ liệu = LONDON1;" _

& "Danh mục ban đầu = Northwind"

Khi có lỗi Đi tới CnErrorHandler

cn.Mở

Thoát phụ

CnErrorHandler:

Đối với mỗi ADOErr trong cn.Errors

Gỡ lỗi.In ADOErr.Number

Debug.Print ADOErr.Description

Kế tiếp

Kết thúcphụ

Trong thực tế, những lỗi điển hình của của kết nối này(KHÔNG Truy cập tập tin, lỗi mật khẩu hoặc tên người dùng khi kết nối với SQL Server, không có quyền, tệp được mở ở chế độ độc quyền, v.v.). và người dùng được nhắc sửa lỗi.

Các thuộc tính quan trọng nhất của đối tượng ADOError:

· Sự miêu tả- mô tả lỗi. Thông thường nhất Thông tin quan trọngđược chứa chính xác trong mô tả.

· Con số- số lỗi. Thật thuận tiện khi tìm kiếm theo số trong cơ sở tri thức và trên Internet.

· Nguồn- nguồn lỗi. Thông tin này chỉ hữu ích nếu bộ sưu tập Lỗi có thể chứa lỗi từ các nguồn khác nhau.

· Trạng thái SQLLỗi gốc- thông tin về lỗi xảy ra từ nguồn dữ liệu tương thích với SQL.