Truy cập cơ sở dữ liệu với .NET - Làm việc với ADO.NET

Phân tầng các ứng dụng

Việc sản xuất các phần mềm tương tác với dữ liệu thường chia ứng dụng

thành nhiều tầng. Một mô hình phổ biến của một ứng dụng phân tầng là các

dịch vụ dữ liệu phân tầng, và một cơ sở dữ liệu phân tầng.

Một trong những cái khó của mô hình này là việc phân tách dữ liệu giữa các

tầng, và định dạng truyền giữa các tầng. ADO.NET đã giải quyết các vấn đề

này và đã sớm hỗ trợ cho kiểu cấu trúc này.

pdf13 trang | Chuyên mục: Visual C# | Chia sẻ: dkS00TYs | Lượt xem: 1857 | Lượt tải: 1download
Tóm tắt nội dung Truy cập cơ sở dữ liệu với .NET - Làm việc với ADO.NET, để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
 thái tương ứng. GetChanges() đơn giản gọi 
GetChanges(Deleted | Modified | Added), và kiểm tra nếu để bảo đảm rằng 
có một vài thay đổi bằng cách gọi HasChanges(). Nếu không có thay đổi 
nào, một giá trị được trả về ngay lập tức. 
Tiếp theo là sao chép DataSet. Trước tiên, một DataSet mới bỏ qua các ràng 
buộc (EnforceConstraints = false), sau đó mỗi dòng đã thay đổi được sao 
chép vào một DataSet mới. 
Như vậy bạn có một DataSet chỉ chứa các thay đổi, sau đó bạn có thể truyền 
dữ liệu này qua các tầng để sử lí. Khi dữ liệu được cập nhật vào cơ sở dữ 
liệu, "changes" DataSet có thể trả về cho trình gọi (trong ví dụ này, một vài 
tham số xuât từ các stored procedure đã cập nhật trong các cột). Những thay 
đổi này có thể trộn vào bộ DataSet bằng cách dùng phương thức Merge(). 
Tiến trình này được mô tả như sau: 
Tạo khoá với SQL Server 
Stored procedure RegionInsert trong ví dụ ở phần trước đã từng tạo ra một 
giá trí khóa chính để chèn vào cơ sở dữ liệu. Phương thức tạo khoá đó còn 
thô sơ và không linh động, vì vậy một ứng dụng thực tế cần dùng đến các kĩ 
thật tạo khóa cao cấp hơn. 
Đầu tiên có thể là định nghĩa một định dạng cột đơn giản, và trả về giá trị 
@@IDENTITY từ một stored procedure. Stored procedure dưới đây sử 
dụng bảng Categories trong cơ sở dữ liệu Northwind. Gõ stored procedure 
này vào SQL Query Analyzer, hoặc chạy the file StoredProcs.sql trong thư 
mục 13_SQLServerKeys: 
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 một dòng mới vào bảng Category, và trả về khóa chính cho trình 
gọi. Bạn có thể kiểm tra procedure này bằng 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 một bó lệnh, nó sẽ chèn mọt dòng mới vào bảng Categories, và 
trả về nhận dạng của dòng mới này, sau đó biểu diễn cho người dùng. 
Giả sử rằng sau một vài tháng sử dụng, một ai đó muốn có một sổ theo dõi 
đơn giản, để báo cáo những cập nhật và sửa đổi trên category name. Bạn sẽ 
định nghĩa một bảng như sau, để chỉ ra các giá trị mới và cũ của category: 
Mã sẵn có trong StoredProcs.sql. Cột AuditID được định nghĩa như một cột 
IDENTITY. Sau đó bạn cấu trúc mọt cặp trigger để báo cáo các thay đổi trên 
trường CategoryName: 
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 và NEW của các dòng, thay vì chèn một trigger nó có một bộ bảng 
trong bộ nhớ gọi là Inserted, để xóa và cập nhật, các dòng cũ tồn tại trong 
bảng Deleted. 
Trigger này nhận CategoryID cho các cột giả và lưu các giá trị cũ và mới 
của cột CategoryName. 
Giờ đây, khi bạn gọi một stored procedure để chèn một CategoryID mới, bạn 
nhận mọt giá trị nhận dạng; Dĩ nhiên, nó không còn là giá trị nhận của dòng 
được chèn vào bảng Categories, nó là một giá trị mới được tạo trong bảng 
CategoryAudit. Ouch! 
Để xem vấn đề, mở SQL Server Enterprise manager, xem nội dung của bảng 
Categories table. 
 Bảng này liệt kê tất cả categories tôi có trong thể hiện của cơ sở dữ liệu. 
Giá trị nhận dạng tiếp theo cho bảng Categories có thể là 21, vì vậy chúng ta 
sẽ chèn một dòng mới bằng cách thực thi mã sau đây, và xem nó trả về ID 
nào: 
DECLARE @CatID int; 
EXECUTE CategoryInsert 'Pasties' , 'Heaven Sent Food' , @CatID 
OUTPUT; 
PRINT @CatID; 
Giá trị trả về trên máy của tôi là 17. Khi xem bảng CategoryAudit, tôi nhận 
ra rằng đó là nhận dạng của dòng mới chèn trong bảng audit, không phải của 
category. 
Đó là vì @@IDENTITY trả về giá trị nhận dạng cuối. 
Có hai nhận dạng cơ bản bạn có thể sử dụng thay cho @@IDENTITY, 
chúng cũng không thể giải quyết vấn đề trên. Đầu tiên là 
SCOPE_IDENTITY(), sẽ trả về giá trị nhận dạng cuối cùng trong tầm vực 
hiện tại. SQL Server định nghĩa tầm vực như như một stored procedure, 
trigger, hoặc hàm. Nếu vì một ai đó thêm một câu lệnh INSERT khác vào 
stored procedure, thì bạn sẽ nhận một giá trị không mong chờ. 
IDENT_CURRENT() sẽ trả về giá trị nhận dạng cuối cùng được phát ra trên 
một bảng trong bất cứ tầm vực nào, trong trường hợp này, nếu hai người 
dùng đang truy cập SQL Server cùng một lúc, nó có thể nhận giá trị của 
người khác. 
Chỉ có cách quản lí thủ công, bằng cách dùng cột IDENTITY trong SQL 
Server. 
Qui tắt đặt tên 
Trong nhiều năm làm việc với các ứng dụng cơ sở dữ liệu, Tôi nhận được 
một vài giới thiệu cho cách đặt tênđể tiện cho việc dùng chung. Tôi biết nó 
không liên quan đến .NET, nhưng những qui tắt này rất hữu ích khi đặt tên. 
Bỏ qua phần này nếu bạn có cách đặt tên riêng của mình. 
Database Tables 
 Luôn là số ít – Product tốt hơn là Products. Nó sẽ tôt hơn về mặt ngữ 
pháp khi nói "The Product table contains products" hơn là "The Products 
table contains products". Hãy xem cơ sở dữ liệu Northwind để thấy được 
nhận xét này. 
 Chấp nhận một vài qui tắt đặt tên cho các cột trong một bảng – chẳng 
hạn _ID cho khóa chính của bảng (Ở đây khóa chính là một cột), tên 
của cột phải là một tên thân thiện, và giải thích chứa đựng thông tin về cột 
đó. Một qui tắc đặt tên tốt sẽ cho bạn một cái nhìn bao quát vè khả năng của 
các trường trong cơ sở dữ liệu. 
Database Columns 
 Dùng danh từ số ít tốt hơn là danh từ số nhiều. 
 Bất kì cột nào liên kết với bảng khác nên được đặt cùng tên với khóa 
chính của bảng kia. Chẳng hạn, một liên kết với bảng Product là Product_ID, 
và đến bảng Sample là Sample_ID. Không phải lúc nào cũng vậy, chẳng hạn 
một bảng có nhiều liên kết với bảng khác. Trong trường hợp này tùy bạn sử 
dụng. 
 Các trường Date nên kết thúc bằng _On, chẳng hạn Modified_On, 
Created_On. Như vậy sẽ dễ hiểu hơn. 
 Các trường báo cao nêu kết thúc bằng _By, chẳng hạn Modified_By 
hay Created_By. 
Constraints 
 Nếu có thể, nên bao gồm tên của bảng và cột của ràng buộc, chẳng 
hạn CK__. Ví dụ CK_PERSON_SEX để kiểm tra ràng buộc 
trên cột SEX của bảng PERSON. Một khóa ngoại có thể là 
FK_Product_Supplier_ID, đây là khóa ngoại giữa product và supplier. 
 Chỉ ra kiểu của ràng buộc như một tiếp đầu ngữ, chẳng hạn CK cho 
một kiểm tra ràng buộc và FK cho một khóa ngoại. Chẳng hạn 
CK_PERSON_AGE_GT0 cho một ràng buộc trên cột age khai báo rằng age 
phải lớn hơn zero. 
 Nếu bạn muốn rút gọn tên của ràng buộc, nên làm điều đó trên tên của 
bảng hơn là tên của cột. Khi bạn có một ràng buộc vi phạm, nó sẽ dễ dàng 
nhận ra lỗi xảy ra trên bảng nào, nhưng không dễ kiểm tra xem trường nào 
đã sinh lỗi. Oracle giới hạn tên là 30-kí tự. 
Stored Procedures 
Nhiều nhà phát triển SQL Server nhận thấy dùng tiếp đầu ngữ 'sp_' là qui tắc 
tốt nhất để đặt tên cho các stored procedure. 
SQL Server dùng tiếp đầu ngữ 'sp_' cho tât cả các stored procedure hệ thống. 
Vì vậy, có thể sẽ xảy ra tình trạng xung đột tên khi các stored procedure của 
bạn cũng bắt đầu là 'sp_' như 'sp_widget' giống với stored procedure chuẩn 
của SQL Server. Khi xem xét một stored procedure, SQL Server sẽ sửa các 
procedure với tiếp đầu ngữ 'sp_'. 
Nêu bạn dùng tiếp đầu ngữ này, khi thực thi, SQL Server sẽ xem tầm vực 
hiện tại, và nhảy đến cơ sở dữ liệu chủ để tìm stored procedure đó. Nếu có 
tồn tại thì sẽ có một lỗi phát sinh sớm. 
Performance 
Bộ managed provider hiện tại của .NET có một vài giới hạn – bạn có thể 
chọn OleDb hoặc SqlClient; OleDb cho phép kết nối với bất kì nguồn dữ 
liệu nào nếu nó là một OLE DB driver (chẳng hạn như Oracle), còn 
SqlClient là một trình cung câp dùng riêng cho SqlServer. 
Trình cung cấp SqlClient đã được viết hoàn toàn bằng mã có quản, và sử 
dụng một vài lớp để kết nối cơ sở dữ liệu. Trình cung cấp viết các gói TDS 
(Tabular Data Stream) trực tiếp từ SQL Server, về bản chất nó nhanh hơn 
OleDb provider, nó có thể duyệt qua các lớp trước khi tác động vào cơ sở dữ 
liệu. 
Để kiểm tra điều đó, hãy chạy mã sau trên cùng cơ sở dữ liệu, khác biệt ở 
chỗ sử dụng SqlClient managed provider trên ADO provider: 
SqlConnection conn = new SqlConnection(Login.Connection); 
conn.Open(); 
SqlCommand cmd = new SqlCommand ( "update tempdata set AValue=1 
Where ID=1" , 
 conn); 
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 hơn là SqlCommand. Tôi đã tạo 
một bảng cơ sở dữ liệu nhỏ với hai côtj như dưới đây, và điền vào đó một 
dòng đơn: 
Câu lệnh SQL được sử dụng là một câu lệnh UPDATE đơn giản: 
UPDATE TempData SET AValue = 1 WHERE ID = 1. 
SQL là đơn giản nhất trong các provider. Kết quả tính bằng giây cho được 
liệt kê trong bảng sau: 
Provider 100 1000 10000 50000 
OleDb 0.109 0.798 7.95 39.11 
Provider 100 1000 10000 50000 
Sql 0.078 0.626 6.23 29.27 
Nếu bạn chỉ hướng vào SQL Server thì dĩ nhiên bạn sẽ chọn Sql provider. 
Trong thực tế, nếu bạn sử dụng các cơ sở dữ liệu khác bạn sẽ sử dụng OleDb 
provider. 
Microsoft đã tạo ra một giao thức tri cập chung cho các cơ sở dữ liệu khác 
nhau trong System.Data.Các lớp chung này sẽ dùng cơ sở dữ liệu thích hợp 
vào thời gian chạy. Nó là một lớp vở bọc giữa OleDb và Sql, nếu các nhà 
cung cấp cơ sở dữ liệu khác viết các trình quản lí cho các sản phẩm của họ, 
bạn có thể dùng ADO cho provider đó với một ít thay đổi ở mã. Ví dụ trong 
truy cập cơ sở dữ liệu .NET, "Scientific Data Center" trong "Data-Centric 
.NET Programming with C#" (Wrox Press, ISBN 1-861005-92-x) giải thích 
việc sử dụgn C# để truy cập cơ sở dữ liệu MySQL. 

File đính kèm:

  • pdf70_4628.pdf