chương 3 truy cập cơ sở dữ liệu với net

45 732 0
chương 3  truy cập cơ sở dữ liệu với net

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Khoa CNTT [MƠI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] Chương 3: Truy cập sở liệu với NET Tổng quan Trong chương này, bàn cách để chương trình C# sử dụng ADO.NET Kết thúc chương này, có kiến thức sau: • • • • Các kết nối sở liệu - để sử dụng lớp SqlConnection OleDbConnection để kết nối huỷ kết nối với sở liệu Các kết nối dùng kiếu giống chuỗi kết nối trình cung cấp OLEDB Sau làm thử vài kết nối sở liệu, phải bảo đảm kết nối đóng lại sau dùng, thơng qua vài ứng dụng đơn giản Các lệnh thực thi - ADO.NET chứa đối tượng command, thực thi SQL, phát stored procedure để trả giá trị Các tùy chọn khác đối tượng command bàn kĩ, với ví dụ cho tuỳ chọn đưa lớp Sql OleDB Stored Procedures - Làm để gọi stored procedure đối tượng command, kết hợp giá trị trả với liệu trình khách The ADO.NET object model - cách truyền đạt khác đến đối tượng có sẵn với ADO, lớp DataSet, DataTable, DataRow, DataColumn bàn kĩ Một DataSet bao gồm quan hệ table, ràng buộc Chúng bàn kĩ 3.1 Giới thiệu ADO.NET Giống hầu hết thành phần NET Framework, ADO.NET không vỏ bọc vài API sẵn có Nó giống ADO tên - lớp phương thức truy xuất liệu khác hoàn toàn ADO (Microsoft's ActiveX Data Objects) thư viên thành phần COM ca ngợi vài năm trở lại Phiên 2.7, thành phần chủ yếu ADO Connection, Command, Recordset, Field object Một connection mở sở liệu, vài liệu chọn vào recordset, bao gồm trường, liệu sau thao tác, cập nhập lên server, connection cần phải đóng lại ADO giới thiệu disconnected recordset, dùng không muốn giữ kếp nối thời gian dài Có vài vấn đề với ADO khơng hài lịng địa chỉ, cồng kềnh disconnected recordset Hỗ trợ khơng cần thiết với tiến hố tin học "webcentric", cần loại bỏ Có số giống lập trình ADO.NET ADO (khơng phải tên), việc chuyển từ ADO khơng qua khó khăn Hơn nữa, bạn dùng SQL Server, có quản tuyệt cho viêc thao tác bên sở liệu Chừng lí đủ để bạn quan tâm đến ADO.NET Nguyễn Minh Hiệp  Page 67  Khoa CNTT [MÔI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] ADO.NET chứa hai khơng gian tên sơ liệu - cho SQL Server, khác cho sở liệu trình bày thơng qua giao diện OLE DB Nếu sở liệu bạn chọn phận OLE DB, bạn dễ dàng kết nối với từ NET cần dùng lớp OLE DB kết nối thông qua driver sở liêu hành bạn 3.1.1 Các Namespace Tất ví dụ chương truy xuất liệu vài cách Các không gian tên sau lớp giao diện dùng cho việc truy xuất liệu NET: • • • • • System.Data - Các lớp truy xuất liệu chung System.Data.Common - Các lớp dùng chung data provider khác System.Data.OleDb - Các lớp OLE DB provider System.Data.SqlClient - Các lớp SQL Server provider System.Data.SqlTypes - Cac kiểu SQL Server Các lớp ADO.NET liệt kê đây: 3.1.2 Các lớp dùng chung ADO.NET chứa số lớp dùng không quan tâm bạn dùng lớp SQL Server lớp OLE DB Các lớp không gian tên System.Data liệt kê sau đây: • • • • • • DataSet - Đối tượng chứa DataTable, bao gồm quan hệ bảng, thiết kế cho truy xuất liệu không kết nối DataTable - Một kho chứa liệu Một DataTable bao gồm nhiều DataColumns, tạo có nhiều DataRows chứa liệu DataRow - Một giá trị, có bà với dòng bảng sở liệu, dịng bảng tính DataColumn - Chứa cá định nghĩa cột, chẳng hạn tên kiểu liệu DataRelation - Một liên kết hai DataTable DataSet Sử dụng cho khóa ngoại mối quan hệ chủ tớ Constraint - Định nghĩa qui tắt cho DataColumn (hoặc môt cột liệu), giá trị độc Sau hai lớp tìm thấy khơng gian tên System.Data.Common: • DataColumnMapping - Ánh xạ tên cột từ sở liệu vào tên cột DataTable Nguyễn Minh Hiệp  Page 68  Khoa CNTT [MƠI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] • DataTableMapping - Ánh xạ tên bảng từ sở liệu vào bảng DataSet 3.1.3 Các lớp sở liệu chuyên biệt Bổ sung cho lớp dùng chung trên, ADO.NET có số lớp liệu chuyên biệt đưa Các lớp thực thi giao diện chuẩn định nghĩa không gian tên System.Data, cho phép sử dụng lớp có kiểu giao diện Ví dụ hai lớp SqlConnection OleDbConnection thực thi giao diện IDbConnection • • • • • • • SqlCommand, OleDbCommand - Một vỏ bọc câu lệnh SQL lời gọi stored procedure SqlCommandBuilder, OleDbCommandBuilder - Một lớp sử dụng câu lệnh SQL (chẳng hạn câu lệnh INSERT, UPDATE, vàDELETE) từ câu lệnh SELECT SqlConnection, OleDbConnection - Kết nối với sở liệu Giống ADO Connection SqlDataAdapter, OleDbDataAdapter - Một lớp giữ câu lệnh select, insert, update, delete, chúng sử dụng để tạo DataSet cập nhật Database SqlDataReader, OleDbDataReader - Chỉ đọc, kết nối với data reader SqlParameter, OleDbParameter - Định nghĩa tham số cho stored procedure SqlTransaction, OleDbTransaction - Một giao tiếp sở liện, bọc đối tượng Một đặc tính quan trọng lớp ADO.NET chúng thiết kế để làm việc môi trường khơng kết nối, đóng vai trị quan trọng giới "web-centric" Nó dùng để kiến trúc server (chẳng hạn mua sách qua mạng) để kết nối server, lấy vài liệu, làm việc liệu PC khách trước kết nối lại truyền liệu trở lại để xử lí ADO 2.1 giới thiệu recordset khơng kết nối, cho phép liệu lấy từ sở liệu, truyền cho trình khách để xử lí Nó thường khó xử dụng cách ứng xử không kết không thiết kế từ đâu Các lớp ADO.NET khác - Sql/OleDb DataReader thiết kết cho để dùng cho sở liệu offline 3.2 Sử dụng Database Connection Trong trìn tự truy xuất sở liệu, bạn cần cung cấp thông số kết nối, chẳng hạn thiết bị mà sở liệu chạy, khả đăng nhập bạn Bất kì làm việc với ADO dễ dàng quen với lớp kết nối NET, OleDbConnection SqlConnection: Nguyễn Minh Hiệp  Page 69  Khoa CNTT [MÔI TRƯỜNG VÀ CÔNG CỤ LẬP TRÌNH] Đoạn mã sau mơ tả cách để tạo, mở đóng kết nối đến sở liệu Northwind Các ví dụ chương dùng sở liệu Northwind, cài đặt chung với ví dụ NET Framework SDK: using System.Data.SqlClient; string source = "server=(local)\\NetSDK;" + "uid=QSUser;pwd=QSPassword;" + "database=Northwind"; SqlConnection conn = new SqlConnection(source); conn.Open(); // Do something useful conn.Close(); Chuỗi kết nối trở nên thân thiện bạn dùng ADO hay OLE DB trước thật vậy, bạn cắt dán từ mã cũ bạn, bạn dùng OleDb provider Trong ví dụ chuỗi kết nối này, tham số dùng sau (các tham số cách dấu chấm phẩy chuỗi kết nối) • • • • server=(local)\\NetSDK - Nó biểu diễn database server kết nối SQL Server cho phép số tiến trình database server processes khác chạy máy, thực kết nối với tiến trình NetSDK máy cụ uid=QSUser - Tham số mô tả người dùng sở liệu Bạn sử dụng User ID pwd=QSPassword - password cho người dùng .NET SDK sở liệu giống nhau, user/password liên kết thêm vào trình cài đặt ví dụ NET Bạn dùng Password database=Northwind - Cái mô tả loại liệu để kết nối - tiến trình SQL Server đưa vài loại liệu khác Ví mở kết nối sở liệu ùng chuỗi kết nối định nghĩa, sau đóng kết nối lại Khi kết nối mở, bạn phát lệnh để thao tác sở liệu, hoàn tất, kết nối đóng lại Nguyễn Minh Hiệp  Page 70  Khoa CNTT [MƠI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] SQL Server có chế độ bảo mật khác - dùng chế độ bảo mật Windows, khả truy cập Windows truyền cho SQL Server Với lựa chọn bạn bỏ vị trí uid pwd chuỗi kết nối, thêm vào Integrated Security=SSPI Trong lúc download mã nguỗn sẵn có cho chương này, bạn cần tìm file Login.cs đơn giãn hóa ví dụ chương Nó kết nối với tất mã ví dụ, bao gồm thơng tin kết nối sở liệu dùng cho ví dụ; sau bạn cung cấp tên server, user, and password cách thích hợp Nếu mặc định dùng Windows integrated security; bạn cần thay đổi username password cho phù hợp Bây biết cách mở kết nối, trước chuyển qua vấn đề khác cần xem xét vài thực hành tốt có liên quan đến kết nối 3.2.1 Sử dụng Connection Một cách tổng quát, sử dụng tài nguyên "hiếm" NET, chẳng hạn kết nối sở liệu, cửa sổ,hoặc đối tượng đồ họa, tốt hết bạn nên đảm bảo tài ngun ln phải đóng lại sau sử dụng xong Dù nhà thiết kết NET làm điều nhờ trình thu gom rác, ln làm sau nhớ sau khoảng thời gian đó, nhiên nên giải phóng sớm tốt Rõ ràng viết mã truy xuất sở liệu, việc giữ kết nối thời gian tốt để không làm ảnh hưởng đến phần khác Trong nhiều tình tiêu cực, khơng đóng kết nối khố khơng cho người dùng khác truy nhập vào bảng liệu đó, tác hại to lớn khả thực thi ứng dụng Việc đóng kết nối sở liệu coi bắt buộc, ứng dụng cách cấu trúc mã bạn để giảm thiểu rủi ro cho mã nguồn mở Có hai cách để đảm bảo kết nối sở liệu giải phóng sau dùng Tùy chọn - try/catch/finally Tùy chọn thứ để đảm bảo tài nguyên dọn sử dụng khối lệnh try…catch…finally, đảm bảo bạn đóng kết nối khối lệnh finally Đây ví dụ nhỏ: try { // Open the connection conn.Open(); // Do something useful } Nguyễn Minh Hiệp  Page 71  Khoa CNTT [MÔI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] catch ( Exception ex ) { // Do something about the exception } finally { // Ensure that the connection is freed conn.Close ( ) ; } Với khối kết nối bạn giải phóng tài ngun mà bạn dùng Vấn đề phương thức bạn phải bảo đảm bạn có đóng kết nối - dễ quên việc thêm vào khối finally, phong cách lập trình tốt quan trọng Ngồi ra, bạn mở số tài nguyên (chẳng hạn hai kết nối sở liệu file) phương thức, đơi khối try…catch…finally trở nên khó đọc Có cách khác để đảm bảo tài nguyên dọn dẹp - sử dụng câu lệnh Tùy chọn hai - Sử dụng khối câu lệnh Trong lúc phát triển C#, phương thức NET's dọn dẹp đối tượng chúng khơng cịn tham chiếu sử dụng huỷ bất định trở thành vấn đề nóng hổi Trong C++, đối tượng rời khỏi tầm vực, khối huỷ tử tự động gọi Nó điều cho nhà thiết cớ lớp sử dụng tài nguyên, huỷ tử sử dụng để đóng tài nguyên người dùng quên làm điều Một huỷe tử C++ gọi đối tượng vượt q tầm vực - ngoại lệ phát mà không chặn, tât hủy tử cần phải gọi Với C# ngơn ngữ có quản khác, tất tự động, khối huỷ tử định trước thay trình thu gom rác, dùng để tháo tài nguyên thời điểm tương lai Chúng mang tính bất định, nghĩa bạn khơng biết trước việc xảy Nếu qn khơng đóng kết nối sở liệu nguyên nhân gây lỗi chạy NET Mã sau giải thích cách để sử dụng giao diện IDisposable (đã bàn kĩ chương 2) để giải phóng tài nguyên thoát khỏi khối using string source = "server=(local)\\NetSDK;" + "uid=QSUser;pwd=QSPassword;" + "database=Northwind"; using ( SqlConnection conn = new SqlConnection ( source ) ) { // Open the connection Nguyễn Minh Hiệp  Page 72  Khoa CNTT [MÔI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] conn.Open ( ) ; // Do something useful } Mệnh đề using giới thiệu chương Đối tượng mệnh đề using phải thực thi giao diện IDisposable, không se tạo lỗi biên dịch Phương thức Dispose() tự động gọi thoát khỏi khối using Khi xem mã IL phương thưc Dispose() SqlConnection (và OleDbConnection), hai kiểm tra trạng thái đối tượng kết nối, mở phương thức Close() gọi Khi lập trình bạn nên dùng hai tùy chọn trên.Ở chỗ bạn cần tài nguyên tốt sử dụng mệnh đề using(), dù bạn sử dụng câu lệnh Close(), qn khơng sử dụng khối lệnh using đóng lại giúp bạn Khơng thay mọt bẫy ngoại lệ tốt, tốt bạn dùng trộn lẫn hai phương thức ví dụ sau: try { using (SqlConnection conn = new SqlConnection ( source )) { // Open the connection conn.Open ( ) ; // Do something useful // Close it myself conn.Close ( ) ; } } catch (Exception e) { // Do something with the exception here } Ở gọi tường minh phương thức Close() điều khơng bắt buộc khối lệnh using làm điều thay cho bạn; nhiên, bạn ln tài ngun giải phóng sớm - bạn có nhiều mã khối lệnh mã khơng khố tài ngun Nguyễn Minh Hiệp  Page 73  Khoa CNTT [MƠI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] Thêm vào đó, ngoại lệ xảy bên khối using, phương thức IDisposable.Dispose gọi để bảo đảm tài nguyên giải phóng, điều đảm bảo kết nối sở liệu ln ln đóng lại Điều làm cho mã dễ đọc đảm bảo kết nối ln đóng ngoại lệ xảy Cuối cùng, bạn viết lớp bao bọc tài ngun có lẽ ln thưc giao diện IDisposable để đóng tài nguyên Bằng cách dùng câu lệnh using() ln đảm bảo tài nguyên dọn dẹp 3.2.2 Transaction (giao dịch) Thường có nhiều cập nhật sở liệu thực thi thực bên tầm vực transaction Một transaction ADO.NET khởi tạo lời gọi đến phương thức BeginTransaction() đối tượng kết nối sở liệu Những phương thức trả đối tượng thực thi giao diện IDbTransaction, định nghĩa System.Data Chuỗi mã lệnh khởi tạo transaction kết nối SQL Server: string source = "server=(local)\\NetSDK;" + "uid=QSUser;pwd=QSPassword;" + "database=Northwind"; SqlConnection conn = new SqlConnection(source); conn.Open(); SqlTransaction tx = conn.BeginTransaction(); // Execute some commands, then commit the transaction tx.Commit(); conn.Close(); Khi bạn khởi tạo transaction, bạn chọn bậc tự cho lệnh thực thi transaction Bậc rõ tự transaction với transaction khác xảy sở liệu Các hệ sở liệu hỗ trợ bốn tùy chọn sau đây: Isolation Level ReadCommitted ReadUncommitted Nguyễn Minh Hiệp  Description Mặc định cho Bậc đảm bảo liệu ghi transaction truy cập transaction khác sau hồn tất cơng việc Tùy chọn cho phép transaction bạn đọc liệu sở liệu, liệu transaction khác sử dụng Ví dụ như, nều hai người dùng truy cập lúc Page 74  Khoa CNTT [MƠI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] Isolation Level RepeatableRead Serializable Description vào sở liệu, người thứ chièn vài liệu transaction họ (đó Commit Rollback), người thứ hai với tuỳ chọn bậc tự ReadUncommitted đọc liệu Bậc mở rộng ReadCommitted, bảo đảm lệnh tương tự phát transaction, ensures that if the same statement is issued within the transaction, regardless of other potential updates made to the database, the same data will always be returned This level does require extra locks to be held on the data, which could adversely affect performance This level guarantees that, for each row in the initial query, no changes can be made to that data It does however permit "phantom" rows to show up - these are completely new rows that another transaction may have inserted while your transaction is running This is the most "exclusive" transaction level, which in effect serializes access to data within the database With this isolation level, phantom rows can never show up, so a SQL statement issued within a serializable transaction will always retrieve the same data The negative performance impact of a Serializable transaction should not be underestimated - if you don't absolutely need to use this level of isolation, it is advisable to stay away from it 3.3 Commands Chúng ta lại nói lại commands Một command một kiểu đơn giản, chuỗi lệnh SQL dùng để truy xuất liệu Một command stored procedure, tên bảng trả về: string source = "server=(local)\\NetSDK;" + "uid=QSUser;pwd=QSPassword;" + "database=Northwind"; string select = "SELECT ContactName,CompanyName FROM Customers"; SqlConnection conn = new SqlConnection(source); conn.Open(); SqlCommand cmd = new SqlCommand(select, conn); Nguyễn Minh Hiệp  Page 75  Khoa CNTT [MÔI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] Các mệnh đề SqlCommand OleDbCommand thường gọi CommandType, chúng dùng để định nghĩa mệnh đề SQL, stored procedure, câu lệnh SQL Sau bảng liệt kê đơn giản CommandType: CommandType Text (default) StoredProcedure TableDirect Example String select = "SELECT ContactName FROM Customers"; SqlCommand cmd = new SqlCommand(select , conn); SqlCommand cmd = new SqlCommand("CustOrderHist", conn); cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.Add("@CustomerID", "QUICK"); OleDbCommand cmd = new OleDbCommand("Categories", conn); cmd.CommandType = CommandType.TableDirect; Khi thực thi stored procedure, cần truyền tham số cho procedure Ví dụ cài đặt trực tiếp tham số @CustomerID, dù có nhiều cách để cài giá trị tham số, sẽbàn kĩ phần sau chương ý: Kiểu TableDirect command không cho OleDb provider – có ngoại lệ xảy bạn cố dùng command Sql provider 3.3.1 Executing Commands Bạn định nghĩa command, bạn muốn thực thi chúng Có số cách để phát statement, dựa vào kết mà bạn muốn command muốn trả Các mệnh đề SqlCommand OleDbCommand cung cấp phương thức thực thi sau: • • • ExecuteNonQuery() – Thực thi command khơng trả kết ExecuteReader() – Thực thi command trả kiểu IDataReader ExecuteScalar() – Thực thi command trả giá trị đơn Lớp SqlCommand cung cấp thêm số phương thức sau • ExecuteXmlReader() – Thực thi command trả đối tượng XmlReader, đối tượng dùng đề xem xét XML trả từ sở liệu ExecuteNonQuery() Phương thức thường dùng cho câu lệnh UPDATE, INSERT, DELETE, để trả số mẫu tin bị tác động Phương thức trả kết thông qua tham số truyền vào stored procedure Nguyễn Minh Hiệp  Page 76  Khoa CNTT [MÔI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] Sau thêm số liệu cho bảng foreach(DataRow theBuilding in ds.Tables["Building"].Rows) { DataRow[] children = theBuilding.GetChildRows("Rooms"); int roomCount = children.Length; Console.WriteLine("Building {0} contains {1} room{2}", theBuilding["Name"], roomCount, roomCount > ? "s" : ""); // Loop through the rooms foreach(DataRow theRoom in children) Console.WriteLine("Room: {0}", theRoom["Name"]); } Sự khác biệt lớn DataSet kiểu đối tượng Recordset cổ điển biểu quan hệ Trong Recordset cổ điển, quan hệ biểu diễn cột giả dịng Cột thân Recordset lập lại Trong ADO.NET, quan hệ đơn giản lời gọi phương thức GetChildRows(): DataRow[] children = theBuilding.GetChildRows("Rooms"); Phương thức có số kiểu, ví dụ cách dùng tên quan hệ Nó trả mảng dịng cập nhật mục đề cập ví dụ trước Thích thú quan hệ liệu xem xét theo hai cách Khơng từ cha đến con, mà tìm dịng cha mẫu tin cách sử dụng thuộc tính ParentRelations lớp DataTable Thuộc tính trả DataRelationCollection, truy cập kí hiệu mảng [] (ví dụ, ParentRelations["Rooms"]), dùng luân phiên phương thức GetParentRows() mã đây: foreach(DataRow theRoom in ds.Tables["Room"].Rows) { DataRow[] parents = theRoom.GetParentRows("Rooms"); Nguyễn Minh Hiệp  Page 97  Khoa CNTT [MÔI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] foreach(DataRow theBuilding in parents) Console.WriteLine("Room {0} is contained in building {1}", theRoom["Name"], theBuilding["Name"]); } Có hai phương thức với nhiều cài đặt đè khác để trả dòng cha – GetParentRows() (trả mảng dòng), GetParentRow() (trả dòng cha quan hệ) 3.5.6 Ràng buộc liệu Thay đổi kiểu liệu cột tạo máy đơn không khả tuyệt vời DataTable ADO.NET cho phép bạn tạo tập ràng buộc cột (hoặc nhiều cột), dùng cho nguyên tắc chuẩn hóa liệu Thời gian chạy hỗ trợ kiểu ràng buộc sau, lớp không gian System.Data Constraint ForeignKeyConstraint UniqueConstraint Description Thực liên kết hai DataTables DataSet Bảo đảm tính độc cột Cài đặt khóa Một điều phổ biến bảng sở liệu quan hệ, bạn cung cấp khóa chính, dựa vào nhiều cột DataTable Mã sau tạo khóa cho bảng Products, mà sơ đồ tạo thủ cơng ví dụ Chú ý khóa cảu bảng kiểu ràng buộc Khi khóa thêm vào DataTable, thời gian chạy phát ràng buộc độc khóa Bởi thực tế khơng tồn kiều ràng buộc PrimaryKey – khóa đơn giản ràng buộc nhiều cột public static void ManufacturePrimaryKey(DataTable dt) { DataColumn[] pk = new DataColumn[1]; pk[0] = dt.Columns["ProductID"]; dt.PrimaryKey = pk; } Nguyễn Minh Hiệp  Page 98  Khoa CNTT [MÔI TRƯỜNG VÀ CÔNG CỤ LẬP TRÌNH] Một khóa bao gồm vài cột, xem mảng DataColumns Một khóa bảng cài đặt cột đơn giản còi mảng cột làm nên thuộc tính Để kiểm tra ràng buộc bảng, bạn lập lại ConstraintCollection Đối với ràng buộc tự sinh ví dụ trên, tên ràng buộc Constraint1 Nó khơng phải tên tốt, tốt nên tạo ràng buộc trước sau định nghĩa cột tạo nên khóa chính, làm Là lập trình viên sở liệu lâu năm, nhận thấy ràng tên ràng buộc cần phải thật rõ nghĩa Mã định danh ràng buộc trước tạo khóa chính: DataColumn[] pk = new DataColumn[1]; pk[0] = dt.Columns["ProductID"]; dt.Constraints.Add(new UniqueConstraint("PK_Products", pk[0])); dt.PrimaryKey = pk; Ràng buộc áp dụng cho cột tùy thích Tạo khóa ngoại Ngồi ràng buộc nhất, DataTable chứa ràng buộc khóa ngoại Nó thường áp dụng cho mối quan hệ chủ tớ, dùng để tạo bảng cột bảng bạng tạo ràng buộc xác Một quan hệ chủ tớ mẫu tin cha có nhiều mẫu tin con, liên kết với khóa mẫu tin cha Một ràng buộc khóa ngoại thực thi bảng bên DataSet, ví dụ sử dụng bảng Categories sở liệu Northwind, tạo ràng buộc với bảng Products table Bước tạo bảng liệu cho bảng Categories Nguyễn Minh Hiệp  Page 99  Khoa CNTT [MƠI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] DataTable categories = new DataTable("Categories"); categories.Columns.Add(new DataColumn("CategoryID", typeof(int))); categories.Columns.Add(new DataColumn("CategoryName", typeof(string))); categories.Columns.Add(new DataColumn("Description", typeof(string))); categories.Constraints.Add(new UniqueConstraint("PK_Categories", categories.Columns["CategoryID"])); categories.PrimaryKey = new DataColumn[1] {categories.Columns["CategoryID"]}; Dòng cuối mã tạo khóa cho bảng Categories Khóa cột đơn, tất nhiên thể tạo khóa nhiều cột dùng kí tự mảng Sau tơi tạo ràng buộc hai bảng: DataColumn parent = ds.Tables["Categories"].Columns["CategoryID"]; DataColumn child = ds.Tables["Products"].Columns["CategoryID"]; ForeignKeyConstraint fk = new ForeignKeyConstraint("FK_Product_CategoryID", parent, child); fk.UpdateRule = Rule.Cascade; fk.DeleteRule = Rule.SetNull; ds.Tables["Products"].Constraints.Add(fk); Ràng buộc dùng để liên kết Categories.CategoryID Products.CategoryID Có bốn cấu trúc khác cho ForeignKeyConstraint, khuyên bạn nên dùng tên ràng buộc Tạo ràng buộc Update Delete Bổ sung cho phần định nghĩa tất nhiên vài kiểu ràng buộc bảng cha con, bạn định nghĩa phải làm ràng buộc cập nhật Ví dụ tạo qui tắc cập nhật qui tắc xóa Những qui tắc dùng mơt kiện phát cột (hoặc dịng) bảng cha, qui tắc dùng để định chuyện xảy bảng Có bốn qui tắc khác áp dụng liệt kê Rule enumeration: • • Cascade – Nếu khóa cha cập nhật sau copy giá trị cho tất mã khóa Nếu mẫu cha bị xố, xóa ln mẫu Nó tùy chọn mặc định None – Khơng làm hết Tùy chọn bỏ dịng mô côi khỏi bảng liệu Nguyễn Minh Hiệp  Page 100  Khoa CNTT [MƠI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] • • SetDefault – Mỗi thay đổi dòng mang giá trị mặc định nó, định nghĩa trước SetNull – Tất dòng chọn DBNull Chú ý: Các ràng buộc có hiệu lực DataSet thuộc tính EnforceConstraints DataSet true 3.6 DataSet Trước tiênn bạn định nghĩa sơ đồ liệu bạn, với đầy đủ DataTable, DataColumn, Constraint, cần thiết, bạn nên tạo DataSet v i vài thơng tin bổ sung Có hai cách để đọc liệu từ nguồn bên ngồi chèn vào DataSet: • • Dùng trình cung cấp liệu Đọc XML vào DataSet 3.6.1 Tạo DataSet dùng DataAdapter Đoạn mã dòng liệu giới thiệu lớp SqlDataAdapter, trình bày sau: string select = "SELECT ContactName,CompanyName FROM Customers"; SqlConnection conn = new SqlConnection(source); SqlDataAdapter da = new SqlDataAdapter(select , conn); DataSet ds = new DataSet(); da.Fill(ds , "Customers"); Hai dòng in đậm cách dùng SqlDataAdapter – OleDbDataAdapter có tính ảo giống Sql equivalent SqlDataAdapter OleDbDataAdapter hai lớp xuất phát từ lớp giao diện, lớp SqlClient- OleDb Cây kế thưa biểu diễn sau: System.Data.Common.DataAdapter System.Data.Common.DbDataAdapter System.Data.OleDb.OleDbDataAdapter System.Data.SqlClient.SqlDataAdapter Trong trình lấy liệu từ DataSet, cần phải có vài lệnh dùng để chọn liệu Nó câu lệnh SELECT, stored procedure, OLE DB Nguyễn Minh Hiệp  Page 101  Khoa CNTT [MƠI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] provider, TableDirect command Ví dụ sử dụng cấu trúc sẵn có SqlDataAdapter để truyền câu lệnh SELECT vào SqlCommand, phát gọi phương thức Fill() adapter Trở lại với ví dụ stored procedures chương trước, Tôi định nghĩa stored procedure INSERT, UPDATE, DELETE, chưa đưa procedure để SELECT liệu Chúng ta lấp lỗ hổng phần sau, cách để gọi stored procedure từ SqlDataAdapter để tạo liệu cho DataSet 3.6.2 Sử dụng Stored Procedure DataAdapter Trước tiên cần định nghĩa stored procedure cài vào sở liệu database.Stored procedure đẻ SELECT liệu sau: CREATE PROCEDURE RegionSelect AS SET NOCOUNT OFF SELECT * FROM Region GO Ví dụ tương đối đơn giản thật khơng xứng tầm với stored procedure, câu lệnh SQL đơn giản Stored procedure đánh vào SQL Server Query Analyzer, bạn chạy file StoredProc.sql để sử dụng ví dụ Tiếp theo, cần định nghĩa SqlCommand để thực thi stored procedure Một lần mã đơn giản, hầu hết đưa phần trên: private static SqlCommand GenerateSelectCommand(SqlConnection conn ) { SqlCommand aCommand = new SqlCommand("RegionSelect" , conn); aCommand.CommandType = CommandType.StoredProcedure; aCommand.UpdatedRowSource = UpdateRowSource.None; return aCommand; } Phương thức phát SqlCommand để gọi thủ tục RegionSelect thực thi Và cuối móc nói với SqlDataAdapter thông qua lời gọi phương thức Fill(): DataSet ds = new DataSet(); // Create a data adapter to fill the DataSet SqlDataAdapter da = new SqlDataAdapter(); // Set the data adapter's select command da.SelectCommand = GenerateSelectCommand (conn); da.Fill(ds , "Region"); Nguyễn Minh Hiệp  Page 102  Khoa CNTT [MÔI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] Ở tơi tạo SqlDataAdapter mới, xem SqlCommand phát thông qua thuộc tính SelectCommand data adapter, gọi Fill(), để thực thi stored procedure chèn tất dòng vào the Region DataTable 3.7 Thay đổi DataSet Sau soạn thạo liệu DataSet, có lúc cần phải thay đổi Một ví dụ phổ biến chọn liệu từ sở liệu, biểu diễ cho người dùng, cập nhật cho sở liệu 3.7.1 Cập nhật với DataAdapter Một SqlDataAdapter bao gồm SelectCommand, InsertCommand, UpdateCommand, DeleteCommand Giống tên gọi, đối tượng thể SqlCommand (hoặc OleDbCommand dùng cho OleDbDataAdapter), câu lệnh chuyển thành SQL stored procedure Trong ví dụ này, khôi phục lại mã stored procedure từ phần Calling Stored Procedures để chèn, cập nhật, xóa mẫu tin Region Chèn dịng Có hai cách để thêm dịng vào DataTable Cách thứ nhât gọi phương thức NewRow, để trả dịng trống sau định vị thêm vào tập Rows sau: DataRow r = ds.Tables["Region"].NewRow(); r["RegionID"]=999; r["RegionDescription"]="North West"; ds.Tables["Region"].Rows.Add(r); Cách thứ hai để thêm dòng truyền mảng liệu vào phương thức Rows.Add() giống sau: DataRow r = ds.Tables["Region"].Rows.Add (new object [] { 999 , "North West" }); Mỗi dòng DataTable cài RowState Added Ví dụ xổ mẫu tin trước thay đổi cập nhật cho liệu, sau thêm dòng sau vào DataTable, dòng giống sau Chú ý cột bên phải trạng thái dòng New row pending inserting into database Eastern Unchanged Western Unchanged Nguyễn Minh Hiệp  Page 103  Khoa CNTT [MƠI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] Northern Southern 999 North West Unchanged Unchanged Added Để cập nhật sở liệu từ DataAdapter, gọi phương thức Update() sau đây: da.Update(ds , "Region"); Đối với dòng DataTable, thực thi stored procedure xuất mẫu tìn DataTable lần New row updated and new RegionID assigned by database Eastern Unchanged Western Unchanged Northern Unchanged Southern Unchanged North West Unchanged Hãy nhìn dịng cuối DataTable Tôi nhập RegionID mã 999, sau đổi RegionInsert stored procedure giá trị đổi thành Có sở liệu thường tạo khố cho bạn SqlCommand aCommand = new SqlCommand("RegionInsert" , conn); aCommand.CommandType = CommandType.StoredProcedure; aCommand.Parameters.Add(new SqlParameter("@RegionDescription" , SqlDbType.NChar , 50 , "RegionDescription")); aCommand.Parameters.Add(new SqlParameter("@RegionID" , SqlDbType.Int, 0, ParameterDirection.Output , false , 0, 0, "RegionID" , // Defines the SOURCE column DataRowVersion.Default , null)); aCommand.UpdatedRowSource = UpdateRowSource.OutputParameters; Nguyễn Minh Hiệp  Page 104  Khoa CNTT [MƠI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] Chuyện xảy data adapter phát lệnh này, tham số xuất ánh xạ trở lại mã nguồn dịng Stored procedure có tham số xuất ánh xạ trở lại DataRow Giá trị UpdateRowSource cho bảng sau: UpdateRowSource Value Description Both Một stored procedure trả nhiều tham số xuất sở liệu gồm mẫu tin cập nhật FirstReturnedRecord Nó trả mẫu liệu đơn, nội dung mẫu tin trộn vào DataRow nguồn Nó có có ích bảng có cột mang giá trị mặc định tính tốn, sau câu lệnh INSERT chúng cần phải đồng với DataRow máy trạm Một ví dụ be 'INSERT (columns) INTO (table) WITH (primarykey)', sau 'SELECT (columns) FROM (table) WHERE (primarykey)' Các mẫu tin trả trộn vào tập dòng None Tất liệu trả từ câu lệnh bị vứt bỏ OutputParameters Bất kì tham số xuât câu lệnh ánh xạ vào cột thích hợp DataRow T Cập nhật dịng có Cập nhật dịng có sẵn DataTable trường hợp việc sử dụng mục lớp DataRow với tên cột số thứ tự cột, giống ví dụ sau đây: r["RegionDescription"]="North West England"; r[1] = "North East England"; Các hai câu lệnh cho kết quả: Changed RegionID Eastern Western Northern Southern North West England Nguyễn Minh Hiệp  description Unchanged Unchanged Unchanged Unchanged Modified Page 105  Khoa CNTT [MÔI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] Trong q trính cập nhật sở liệu, trạng dòng cập nhật gán Modified RowXóa dịng Xóa dịng kết việc gọi phương thức Delete(): r.Delete(); Một dịng xóa có trạng thái Deleted, bạn khơng thể đọc cột từ dịng xố, khơng cịn giá trị Khi gọi phương thức Update(), tất dịng bị xố sử dụng DeleteCommand, trường hợp chạy stored procedure RegionDelete 3.8 Làm việc với ADO.NET Phần cuối cố gắng đưa kịch phổ biến phát triển ứng dụng truy cập sở liệu với ADO.NET 3.8.1 Phân tầng ứng dụng Việc sản xuất phần mềm tương tác với liệu thường chia ứng dụng thành nhiều tầng Một mô hình phổ biến ứng dụng phân tầng dịch vụ liệu phân tầng, sở liệu phân tầng Một khó mơ hình việc phân tách liệu tầng, định dạng truyền tầng ADO.NET giải vấn đề sớm hỗ trợ cho kiểu cấu trúc Sao chép trộn liệu Thật khó để copy DB recordset? Trong In NET thậy dễ dàng để chép DataSet: DataSet source = {some dataset}; DataSet dest = source.Copy(); Nó tạo copy DataSet nguồn – DataTable, DataColumn, DataRow, Relation chép y chan, tất liệu với trạng thái file nguồn đươc chép Nếu bạn muốn chép sơ đồ DataSet, bạn làm sau: DataSet source = {some dataset}; Nguyễn Minh Hiệp  Page 106  Khoa CNTT [MÔI TRƯỜNG VÀ CÔNG CỤ LẬP TRÌNH] DataSet dest = source.Clone(); Nó chép tất table, relation, vân vân Tất nhiên, DataTable rỗng Một thực tế phổ biến viết hệ thống phân tầng, dựa Win32 web, có truyền liệu lớp tốt DataSet có phương thưc GetChanges() để giải yêu cầu Phương thức đơn giản thực thi loạt công việc trả DataSet với dòng cập nhật dataset nguồn Đây ý tưởng truyền liệu tầng, tập nhở liệu truyền Ví dụ sau cách tạo "changes" DataSet: DataSet source = {some dataset}; DataSet dest = source.GetChanges(); Bên lớp vỏ bọc nhiều thứ hấp dẫn Có hai tải phương thức GetChanges() Một tải lấy giá trị DataRowState, trả trạng thái tương ứng GetChanges() đơn giản gọi GetChanges(Deleted | Modified | Added), kiểm tra để bảo đảm có vài thay đổi cách gọi HasChanges() Nếu khơng có thay đổi nào, giá trị trả Tiếp theo chép DataSet Trước tiên, DataSet bỏ qua ràng buộc (EnforceConstraints = false), sau dịng thay đổi chép vào DataSet Như bạn có DataSet chứa thay đổi, sau bạn truyền liệu qua tầng để sử lí Khi liệu cập nhật vào sở liệu, "changes" DataSet trả cho trình gọi (trong ví dụ này, vài tham số xuât từ stored procedure cập nhật cột) Những thay đổi trộn vào DataSet cách dùng phương thức Merge() Tiến trình mơ tả sau: 3.8.2 Tạo khố với SQL Server Nguyễn Minh Hiệp  Page 107  Khoa CNTT [MÔI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] Stored procedure RegionInsert ví dụ phần trước tạo giá trí khóa để chèn vào sở liệu Phương thức tạo khố cịn thơ sơ khơng linh động, ứng dụng thực tế cần dùng đến kĩ thật tạo khóa cao cấp Đầu tiên định nghĩa định dạng cột đơn giản, trả giá trị @@IDENTITY từ stored procedure Stored procedure sử dụng bảng Categories sở liệu Northwind Gõ stored procedure vào SQL Query Analyzer: CREATE PROCEDURE CategoryInsert(@CategoryName NVARCHAR(15), @Description NTEXT, @CategoryID INTEGER OUTPUT) AS SET NOCOUNT OFF INSERT INTO Categories (CategoryName, Description) VALUES(@CategoryName, @Description) SELECT @CategoryID = @@IDENTITY GO Nó chèn dịng vào bảng Category, trả khóa cho trình gọi Bạn kiểm tra procedure cách gõ dòng SQL sau vào Query Analyzer: DECLARE @CatID int; EXECUTE CategoryInsert 'Pasties' , 'Heaven Sent Food' , @CatID OUTPUT; PRINT @CatID; Khi thực thi bó lệnh, chèn mọt dịng vào bảng Categories, trả nhận dạng dòng này, sau biểu diễn cho người dùng Giả sử sau vài tháng sử dụng, muốn có sổ theo dõi đơn giản, để báo cáo cập nhật sửa đổi category name Bạn định nghĩa bảng sau, để giá trị cũ category: Mã sẵn có StoredProcs.sql Cột AuditID định nghĩa cột IDENTITY Sau bạn cấu trúc mọt cặp trigger để báo cáo thay đổi trường CategoryName: Nguyễn Minh Hiệp  Page 108  Khoa CNTT [MÔI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] CREATE TRIGGER CategoryInsertTrigger ON Categories AFTER UPDATE AS INSERT INTO CategoryAudit(CategoryID , OldName , NewName ) SELECT old.CategoryID, old.CategoryName, new.CategoryName FROM Deleted AS old, Categories AS new WHERE old.CategoryID = new.CategoryID; GO Bạn phải dùng Oracle stored procedure, SQL Server không hỗ trợ nội dung OLD NEW dịng, thay chèn trigger có bảng nhớ gọi Inserted, để xóa cập nhật, dịng cũ tồn bảng Deleted Trigger nhận CategoryID cho cột giả lưu giá trị cũ cột CategoryName Giờ đây, bạn gọi stored procedure để chèn CategoryID mới, bạn nhận giá trị nhận dạng; Dĩ nhiên, khơng cịn giá trị nhận dịng chèn vào bảng Categories, giá trị tạo bảng CategoryAudit Ouch! Để xem vấn đề, mở SQL Server Enterprise manager, xem nội dung bảng Categories table Bảng liệt kê tất categories tơi có thể sở liệu Giá trị nhận dạng cho bảng Categories 21, chèn dòng cách thực thi mã sau đây, xem trả ID nào: DECLARE @CatID int; EXECUTE CategoryInsert 'Pasties' , 'Heaven Sent Food' , @CatID OUTPUT; Nguyễn Minh Hiệp  Page 109  Khoa CNTT [MÔI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] PRINT @CatID; Giá trị trả máy 17 Khi xem bảng CategoryAudit, tơi nhận nhận dạng dịng chèn bảng audit, khơng phải category Đó @@IDENTITY trả giá trị nhận dạng cuối Có hai nhận dạng bạn sử dụng thay cho @@IDENTITY, chúng giải vấn đề Đầu tiên SCOPE_IDENTITY(), trả giá trị nhận dạng cuối tầm vực SQL Server định nghĩa tầm vực như stored procedure, trigger, hàm Nếu thêm câu lệnh INSERT khác vào stored procedure, bạn nhận giá trị khơng mong chờ IDENT_CURRENT() trả giá trị nhận dạng cuối phát bảng tầm vực nào, trường hợp này, hai người dùng truy cập SQL Server lúc, nhận giá trị người khác Chỉ có cách quản lí thủ cơng, cách dùng cột IDENTITY SQL Server 3.8.3 Performance Bộ managed provider NET có vài giới hạn – bạn chọn OleDb SqlClient; OleDb cho phép kết nối với nguồn liệu OLE DB driver (chẳng hạn Oracle), SqlClient trình cung câp dùng riêng cho SqlServer Trình cung cấp SqlClient viết hoàn toàn mã có quản, sử dụng vài lớp để kết nối sở liệu Trình cung cấp viết gói TDS (Tabular Data Stream) trực tiếp từ SQL Server, chất nhanh OleDb provider, duyệt qua lớp trước tác động vào sở liệu Để kiểm tra điều đó, chạy mã sau sở liệu, khác biệt chỗ sử dụng SqlClient managed provider ADO provider: SqlConnection conn = new SqlConnection(Login.Connection); conn.Open(); SqlCommand cmd = new SqlCommand ( "update tempdata set AValue=1 Where ID=1" , conn); Nguyễn Minh Hiệp  Page 110  Khoa CNTT [MÔI TRƯỜNG VÀ CƠNG CỤ LẬP TRÌNH] DateTime initial, elapsed ; initial = DateTime.Now ; for(int i = 0; i < iterations; i++) cmd.ExecuteNonQuery(); elapsed = DateTime.Now ; conn.Close(); OLE DB thường sử dụng OleDbCommand SqlCommand Tôi tạo bảng sở liệu nhỏ với hai côtj đây, điền vào dịng đơn: Câu lệnh SQL sử dụng câu lệnh UPDATE đơn giản: UPDATE TempData SET AValue = WHERE ID = SQL đơn giản provider Kết tính giây cho liệt kê bảng sau: Provider OleDb Sql 100 0.109 0.078 1000 0.798 0.626 10000 7.95 6.23 50000 39.11 29.27 Nếu bạn hướng vào SQL Server dĩ nhiên bạn chọn Sql provider Trong thực tế, bạn sử dụng sở liệu khác bạn sử dụng OleDb provider Nguyễn Minh Hiệp  Page 111  ... RegionDelete 3. 8 Làm việc với ADO .NET Phần cuối cố gắng đưa kịch phổ biến phát triển ứng dụng truy cập sở liệu với ADO .NET 3. 8.1 Phân tầng ứng dụng Việc sản xuất phần mềm tương tác với liệu thường... DataTable 3. 7 Thay đổi DataSet Sau soạn thạo liệu DataSet, có lúc cần phải thay đổi Một ví dụ phổ biến chọn liệu từ sở liệu, biểu diễ cho người dùng, cập nhật cho sở liệu 3. 7.1 Cập nhật với DataAdapter... ExecuteReader()) cho phép bạn lấy mẫu tin trả 3. 4 Truy cập nhanh sở liệu với Data Reader Một data reader cách đơn giản nhanh để chọn vài liệu từ nguồn sơ liệu, tính Bạn truy xuất trực tiếp đối tượng data

Ngày đăng: 04/07/2014, 22:48

Từ khóa liên quan

Mục lục

  • Chương 3: Truy cập cơ sở dữ liệu với .NET

  • 3.3 Commands

    • 3.3.1 Executing Commands

      • ExecuteNonQuery()

      • ExecuteReader()

      • ExecuteScalar()

      • ExecuteXmlReader() (SqlClient Provider Only)

      • 3.3.2 Gọi các Stored Procedure

        • Gọi một Stored Procedure không trả lại kết quả

          • Record Update

          • Record Deletion

          • 3.3.3 Gọi Stored Procedure có các tham số trả về

            • Record Insertion

            • 3.4 Truy cập nhanh cơ sở dữ liệu với Data Reader

            • 3.5 Managing Data và Relationships: The DataSet

              • 3.5.1 DataTable

                • 3.5.2 DataColumn

                • 3.5.3 DataRow

                • 3.5.4 Schema Generation

                  • Runtime Schema Generation

                  • Hand-Coded Schema

                  • 3.5.5 Các quan hệ dữ liệu (Relationships)

                  • 3.5.6 Ràng buộc dữ liệu

                    • Cài đặt khóa chính

                    • Tạo một khóa ngoại

                    • Tạo các ràng buộc Update và Delete

                    • 3.6 DataSet

                      • 3.6.1 Tạo một DataSet dùng một DataAdapter

                        • 3.6.2 Sử dụng một Stored Procedure trong một DataAdapter

                        • 3.7 Thay đổi DataSet

                          • 3.7.1 Cập nhật với DataAdapter

                            • Chèn một dòng mới

                            • Cập nhật một dòng đã có

Tài liệu cùng người dùng

Tài liệu liên quan