Để thực hiện các lệnh đến cơ sở dữ liệu, chúng ta cần mở một kết nối và một đối tượng để thực hiện lệnh (command object). Phần 1 chúng ta đã tìm hiểu cách mở một kết nối, trong phần này chúng ta sẽ tìm hiểu cách tạo và dùng đối tượng lệnh và cũng lưu ý phần này chỉ đề cập đến provider là SQL Server.

Đối tượng DbCommand

Chúng ta dùng đối tượng DbCommand để gửi các lệnh truy vấn SQL đến data store. DbCommand có thể là một lệnh DML (Data Manipulation Language) để thêm, xoá, sửa dữ liệu; có thể là một lệnh DDL (Data Definition Language) cho phép tạo các bảng hay chỉnh sửa thông tin lược đồ (schema) của database.

DbCommand yêu cầu mở một kết nối với đối tượng DbConnection trước khi gửi lệnh đến data store. Đối tượng DbConnection có thể:

  • Chuyển vào hàm constructor của đối tượng DbCommand (xem trong sides);
  • Gán đến thuộc tính Connection của đối tượng DbCommand (xem trong slides);
  • Dùng phương thức CreateCommand của đối tượng DbConnection.

DbCommand cũng yêu cầu giá trị hợp lệ cho các thuộc tính CommandTextCommandType tương ứng như sau:

CommandType CommandText
StoredProcedure Tên của một thủ tục lưu trú trong SQL Server
TableDirect Tên của một bảng dữ liệu (chỉ hỗ trợ cho provider OleDb)
Text Một chuỗi lệnh SQL

 

Ví dụ 1: tạo một kết nối và một lệnh là một thủ tục lưu trú (stored procedure) tên ABC

Mã VB:


Dim nw = ConfigurationManager.ConnectionStrings("nw")

Dim connection = New SqlConnection()

connection.ConnectionString = nw.ConnectionString

Dim cmd = connection.CreateCommand()

cmd.CommandType = CommandType.StoredProcedure

cmd.CommandText = "ABC"

…………

Mã C#


var nw = ConfigurationManager.ConnectionStrings["nw"];

var connection = new SqlConnection(nw.ConnectionString);

var cmd = connection.CreateCommand();

cmd.CommandType = CommandType.StoredProcedure;

cmd.CommandText = "ABC";

……….

Ví dụ 2: tạo một kết nối và một lệnh là một chuỗi lệnh SQL

Mã VB:


Dim nw = ConfigurationManager.ConnectionStrings("nw")

Dim connection = New SqlConnection()

connection.ConnectionString = nw.ConnectionString

Dim cmd = connection.CreateCommand()

cmd.CommandType = CommandType.Text

cmd.CommandText = "Select * from Student"

…………

Mã C#


var nw = ConfigurationManager.ConnectionStrings["nw"];

var connection = new SqlConnection(nw.ConnectionString);

var cmd = connection.CreateCommand();

cmd.CommandType = CommandType.Text;

cmd.CommandText = " Select * from Student ";

……….

Đối tượng DbParameter

Thủ tục lưu trú hay chuỗi lệnh SQL thường yêu cầu  chuyển các giá trị tham số đến chúng để thực thi, ví dụ thủ tục hay chuỗi lệnh yêu cầu ID của một sinh viên để lấy thông tin về sinh viên đó. Để thực hiện điều này, chúng ta sẽ tạo một đối tượng System.Data.Common.DbParameter bằng cách dùng phương thức Parameters.Add của đối tương DbCommand như minh hoạ yêu cầu một tham số tên Id và được gán giá trị là 004  sau:

VB


Dim nw = ConfigurationManager.ConnectionStrings("nw")

Dim connection = New SqlConnection()

connection.ConnectionString = nw.ConnectionString

Dim cmd = connection.CreateCommand()

cmd.CommandType = CommandType.StoredProcedure

cmd.CommandText = "ABC"

Dim parm = cmd.CreateParameter()

parm.ParameterName = "@Id"

parm.Value = "004"

cmd.Parameters.Add(parm)

Dim id = cmd.Parameters("@Id").Value

Mã C#


var nw = ConfigurationManager.ConnectionStrings["nw"];

var connection = new SqlConnection();

connection.ConnectionString = nw.ConnectionString;

var cmd = connection.CreateCommand();

cmd.CommandType = CommandType.StoredProcedure;

cmd.CommandText = "ABC";

DbParameter parm = cmd.CreateParameter();

parm.ParameterName = "@Id";

parm.Value = "004";

cmd.Parameters.Add(parm);

var id = (string)cmd.Parameters["@Id"].Value;

Phương thức ExecuteNonQuery

Chúng ta dùng phương thức ExecuteNonQuery chỉ khi không cần kết quả trả về là một hay nhiều hàng, ExecuteNonQuery chỉ trả về một số nguyên là số hàng bị ảnh hưởng bởi lệnh.

Phương thức ExecuteReader

Trả về một đối tượng DbDataReader (sẽ tìm hiểu phần sau).

Phương thức ExecuteScalar

Thực hiện truy vấn và trả về cột đầu tiên ở hàng đầu tiên trong tập kết quả được trả về bởi truy vấn. ExecuteScalar nhận một giá trị đơn từ cơ sở dữ liệu nên sử dụng ít tài nguyên và khả năng thực thi tốt hơn dùng phương thứ ExecuteReader.

Đối tượng DbDataReader

Đối tượng DbDataReader cung cấp một phương thức hiệu quả cao để nhận dữ liệu từ data store; là một lựa chọn tốt cho ListBox hay DropDownList. Đối tượng DbDataReader là tốt nếu chúng ta muốn nhận dữ liệu từ data store nhưng sẽ không hiệu quả nếu chúng ta muốn chỉnh sửa thông tin và cập nhật trở lại data store – lúc này nên dùng DbDataAdapter (tìm hiểu phần sau).

Đối tượng DbDataReader dùng phương thức Read để nhận dữ liệu từ data store và chứa trong vùng đệm (buffer) của nó. Chỉ một hàng được đọc tại một thời điểm, điều này có nghĩa rằng dữ liệu từ data store không cần phải được đọc toàn bộ vào trong ứng dụng trước khi nó được xử lý.

Dùng MARS (Mutiple Active Result Sets) để thực thi nhiều lệnh trong cùng một kết nối

Dùng đối tượng DbDataReader là phương pháp hiệu quả nhất để nhận dữ liệu từ data store nhưng khi thực hiện một lệnh nó sẽ duy trì trạng kết nối đến data store cho đến khi lệnh hoàn tất. Nếu lệnh thứ nhất chưa hoàn tất và chúng ta thực hiện lệnh thứ hai thì một ngoại lệ (InvalidOperatonException) sẽ phát sinh.

Một giải pháp là cho phép thực hiện nhiều lệnh với MARS bằng cách thiết lập giá trị true cho tuỳ chọn MultipleActiveResultSets trong chuỗi kết nối. Khai báo một chuỗi kết nối mới tên nwMars trong tập tin cấu hình như ví dụ sau:

<configuration>

<connectionStrings>

<clear/>

<add Name="nw"

providerName = " System.Data.SqlClient "

connectionString = "Data Source=.\SQLEXPRESS;

AttachDbFilename=|DataDirectory|\Student.MDF; Integrated

Security=True; User Instance=True; "

/>

<add Name="nwMars"

providerName = " System.Data.SqlClient "

connectionString = "Data Source=.\SQLEXPRESS;

AttachDbFilename=|DataDirectory|\Student.MDF; Integrated

Security=True; User Instance=True; MultipleActiveResultSets =True"

/>

</connectionStrings>

....

</configuration>

Tiện ích của MARS:

  • Giúp việc lập trình dễ dàng hơn bằng cách tạo ra một kết nối cho mỗi lệnh. Tuy nhiên, MARS có thể phát sinh những ảnh hưởng tiêu cực (do cho phép nhiều lệnh đồng thời) do đó nên tắt MARS (thiết lập giá trị false cho tuỳ chọn MultipleActiveResultSets) nếu không cần thiết.
  • Có thể tiết kiệm kinh phí do không lệ thuộc vào số lượng kết nối của khách hàng đến database (có thể thực hiện nhiều lệnh cho một kết nối).

Xét ví dụ dùng MARS như sau:

Mã VB


Dim nw = ConfigurationManager.ConnectionStrings("nwMars")

Using connection = New SqlConnection()

connection.ConnectionString = nw.ConnectionString

Dim cmd = connection.CreateCommand()

cmd.CommandType = CommandType.Text

cmd.CommandText = "SELECT CustomerID, CompanyName FROM Customers"

connection.Open()

Dim rdr = cmd.ExecuteReader()

While rdr.Read()

Dim OrdersCmd = connection.CreateCommand()

OrdersCmd.CommandType = CommandType.Text

OrdersCmd.CommandText = _

"SELECT COUNT(OrderID) FROM Orders WHERE (CustomerID = @CustId)"

Dim parm = OrdersCmd.CreateParameter()

parm.ParameterName = "@CustId"

parm.Value = rdr("CustomerID")

OrdersCmd.Parameters.Add(parm)

Dim qtyOrders = OrdersCmd.ExecuteScalar()

MessageBox.Show( _

rdr("CompanyName").ToString() + ": " + qtyOrders.ToString())

End While

End Using

Mã C#


var nw = ConfigurationManager.ConnectionStrings["nwMars"];

using(var connection = new SqlConnection())

{

connection.ConnectionString = nw.ConnectionString;

var cmd = connection.CreateCommand();

cmd.CommandType = CommandType.Text;

cmd.CommandText = "SELECT CustomerID, CompanyName FROM

Customers";

connection.Open();

var rdr = cmd.ExecuteReader();

while (rdr.Read())

{

var ordersCmd = connection.CreateCommand();

ordersCmd.CommandType = CommandType.Text;

ordersCmd.CommandText = "SELECT COUNT(OrderID) FROM Orders WHERE (CustomerID = @CustId)";

var parm = ordersCmd.CreateParameter();

parm.ParameterName = "@CustId";

parm.Value = rdr["CustomerID"];

ordersCmd.Parameters.Add(parm);

var qtyOrders = ordersCmd.ExecuteScalar();

MessageBox.Show(rdr["CompanyName"].ToString() + ": "

+ qtyOrders.ToString());

}

}

Sao chép số lượng lớn dữ liệu với đối tượng SqlBulkCopy

SQL Server hỗ trợ nhiều phương tiện để thực hiện việc copy dữ liệu từ database đến vị trí khác như SQL Server Enterprise Manager (giao diện đồ hoạ) hay SQL Server Bulk Copy Program (tập tin BCP.exe) (giao diện dòng lệnh). Chúng ta cũng có thể viết riêng chương trình copy dữ liệu cho riêng mình với lớp SqlBulkCopy.

Lớp SqlBulkCopy cung cấp phương thức WriteToServer để copy dữ liệu đến một bảng trong cơ sở dữ liệu trong SQL Server và tuỳ vào nguồn (DataRow, DataTable,…) mà chúng ta quá tải (overload)  phương thức WriteToServer cho phù hợp. Hình ảnh minh hoạ về SqlBulkCopyWriteToServer như sau:

Xem ví dụ minh hoạ copy dữ liệu từ bảng Customer trong cơ sở dữ liệu Northwind đến bảng CustomerList trong cơ sở dữ liệu SQL Server tên là BulkCopy:

Mã VB

Dim nw = ConfigurationManager.ConnectionStrings("nw")

Dim nwConnection = New SqlConnection()

nwConnection.ConnectionString = nw.ConnectionString

Dim bulkCopy = ConfigurationManager.ConnectionStrings("BulkCopy")

Dim bulkConnection = New SqlConnection()

bulkConnection.ConnectionString = bulkCopy.ConnectionString

Dim cmd = nwConnection.CreateCommand()

cmd.CommandType = CommandType.Text

cmd.CommandText = "SELECT CustomerID, CompanyName FROM Customers"

nwConnection.Open()

bulkConnection.Open()

Dim rdr = cmd.ExecuteReader()

Dim bc As New SqlBulkCopy(bulkConnection)

bc.DestinationTableName = "StoreList"

bc.WriteToServer(rdr)

nwConnection.Close()

bulkConnection.Close()

MessageBox.Show("Done with bulk copy")

Mã C#

var nw = ConfigurationManager.ConnectionStrings["nw"];

var nwConnection = new SqlConnection();

nwConnection.ConnectionString = nw.ConnectionString;

var bulkCopy = ConfigurationManager.ConnectionStrings["BulkCopy"];

var bulkConnection = new SqlConnection();

bulkConnection.ConnectionString = bulkCopy.ConnectionString;

var cmd = nwConnection.CreateCommand();

cmd.CommandType = CommandType.Text;

cmd.CommandText = "SELECT CustomerID, CompanyName FROM Customers";

nwConnection.Open();

bulkConnection.Open();

var rdr = cmd.ExecuteReader();

var bc = new SqlBulkCopy(bulkConnection);

bc.DestinationTableName = "CustomerList";

bc.WriteToServer(rdr);

nwConnection.Close();

bulkConnection.Close();

MessageBox.Show("Done with bulk copy");

Đối tượng DbDataAdapter

Chúng ta dùng đối tượng DbDataAdapter để nhận và cập nhật dữ liệu giữa một bảng dữ liệu và database. Như những đối tượng khác ở trên (DbConnection, DbCommand,…), DbDataAdapter thừa kế từ lớp cơ sở DataAdapter và mỗi nhà cung cấp sẽ có một lớp DbDataAdapter được thừa kế tương ứng như hình sau:

Khi cần nhận dữ liệu, DbDataAdapter dùng thuộc tính SelectCommand; khi cần cập nhật dữ liệu trở lại database, DbDataAdapter dùng các thuộc tính InsertCommand, UpdateCommand, và DeleteCommand.

Trước khi nhận hay cập nhật dữ liệu, DbDataAdapter sẽ kiểm tra trạng thái kết nối. Nếu kết nếu mở, DbDataAdapter sẽ dùng nó, nếu kết nối bị đóng thì DbDataAdapter sẽ mở kết nối, sử dụng nó, và sẽ đóng kết nối một cách tự động.

Phương thức Fill

Chuyển dữ liệu từ database đến đối tượng DataTable mà chúng ta chuyển vào phương thức Fill như tham số. Có nhiều phiên bản phương thức Fill (quá tải), có phương thức Fill chỉ nhận duy nhất một tham số là một đối tượng DataSet. Trong trường hợp một DataSet được chuyển tới Fill, một đối tượng DataTable mới sẽ được tạo. Xem ví dụ minh hoạ dùng Fill:

Mã VB

Dim nw = ConfigurationManager.ConnectionStrings("nw")

Dim connection = New SqlConnection()

connection.ConnectionString = nw.ConnectionString

Dim cmd = CType(connection.CreateCommand(), SqlCommand)

cmd.CommandType = CommandType.Text

cmd.CommandText = "SELECT CustomerID, CompanyName FROM Customers"

Dim nwSet As New DataSet("nw")

Dim da As New SqlDataAdapter(cmd)

da.Fill(nwSet, "Customers")

MessageBox.Show("DataSet Filled")

Mã C#

var nw = ConfigurationManager.ConnectionStrings["nw"];

var connection = new SqlConnection();

connection.ConnectionString = nw.ConnectionString;

var cmd = (SqlCommand)connection.CreateCommand();

cmd.CommandType = CommandType.Text;

cmd.CommandText = "SELECT CustomerID, CompanyName FROM Customers";

var da = new SqlDataAdapter(cmd);

var nwSet = new DataSet("nw");

da.Fill(nwSet, "Customers");

MessageBox.Show("DataSet Filled");

Nếu chúng ta cần lưu trữ dữ liệu thay đổi, cân nhắc sử dụng mỗi DbDataAdapter cho mỗi bảng dữ liệu (thay vì dùng một DbDataAdapter), như minh hoạ hình dưới dùng hai DbDataAdapter cho hai bảng là CustomersSales:

Phương thức Update

Update lưu các thay đổi từ bảng dữ liệu và sẽ gửi trở lại database. Để phương thức Update làm việc, cần một trong hai điều kiện sau:

  • Tất cả các thuộc tính SelectCommand, UpdateCommand, InsertCommand, và DeleteCommand phải được gán đến đối tượng DbDataAdapter.
  • Dùng đối tượng DbCommandBuilder để tạo các thuộc tính SelectCommand, UpdateCommand, InsertCommand, và DeleteCommand.

Xem đoạn mã minh hoạ cập nhật dữ liệu đến database và hiển thị trên DataGridView:

Mã VB

Dim nw = ConfigurationManager.ConnectionStrings("nw")

Dim connection = New SqlConnection()

connection.ConnectionString = nw.ConnectionString

Dim cmd = connection.CreateCommand()

cmd.CommandType = CommandType.Text

cmd.CommandText = "SELECT * FROM Customers"

Dim nwSet As New DataSet("nw")

Dim da As New SqlDataAdapter(cmd)

Dim bldr As New SqlCommandBuilder(da)

da.Fill(nwSet, "Customers")

'Chỉnh sửa hàng **************************

Dim customersTable = nwSet.Tables("Customers")

Dim updRow = customersTable.Select("CustomerID='WOLZA'")(0)

updRow("CompanyName") = "New Wolza Company"

'Thêm hàng mới*********************************

customersTable.Rows.Add( _

"AAAAA", "Five A Company")

'Xoá một hàng, lưu ý ràng buộc*************************

Dim delRow = customersTable.Select("CustomerID='PARIS'")(0)

delRow.Delete()

'Cập nhật thay đổi đến dataase ********************

da.Update(nwSet, "Customers")

'Hiển thị ra DataGridView ********************

DataGridView2.DataSource = nwSet

DataGridView2.DataMember = "Customers"

MessageBox.Show("Update Complete")

Mã C#

var nw = ConfigurationManager.ConnectionStrings["nw"];

var connection = new SqlConnection();

connection.ConnectionString = nw.ConnectionString;

var cmd = connection.CreateCommand();

cmd.CommandType = CommandType.Text;

cmd.CommandText = "SELECT * FROM Customers";

var da = new SqlDataAdapter(cmd);

var nwSet = new DataSet("nw");

var bldr = new SqlCommandBuilder(da);

da.Fill(nwSet, "Customers");

//Chỉnh sửa hàng **************************

var customersTable = nwSet.Tables["Customers"];

var updRow = customersTable.Select("CustomerID='WOLZA'")[0];

updRow["CompanyName"] = "New Wolza Company";

//Thêm hàng mới*********************************

customersTable.Rows.Add(

"AAAAA", "Five A Company");

//Xoá một hàng, lưu ý ràng buộc*************************

var delRow = customersTable.Select("CustomerID='PARIS'")[0];

delRow.Delete();

//Cập nhật thay đổi đến dataase ********************

da.Update(nwSet, "Customers");

'Hiển thị ra DataGridView ********************

dataGridView2.DataSource = nwSet;

dataGridView2.DataMember = "Customers";

MessageBox.Show("Update Complete");

Cập nhật dữ liệu đến database theo lô (batches)

Phương thức Update chúng ta đã đề cập ở trên áp dụng nguyên tắc cập nhật dữ liệu theo từng hàng. Một giải pháp khác là áp dụng cập nhật theo lô (batches) – hay nhiều hàng một lúc. Để áp dụng cập nhật theo lô, chúng ta thiết lập một giá trị đến thuộc tính UpdateBatchSize của đối tượng DbDataAdapter. Mặc định, giá trị của UpdateBatchSize là 1 (cập nhật từng hàng một). Ví dụ bảng Customers chứa 91 hàng, thuộc tính UpdateBatchSize = 40 thì khi phương thức Update thực thi, thay đổi được gửi đến database theo 3 lô: lô 1 gồm 40 thay đổi, lô 2 gồm 40 thay đổi, và lô 3 gồm 11 thay đổi. Minh hoạ mã VB và C#:

Mã VB

Private WithEvents da As New SqlDataAdapter()

Private sb as New System.Text.StringBuilder()

private sub rowUpdated(byval sender as Object, _

byval e as SqlRowUpdatedEventArgs) handles da.RowUpdated

sb.Append("Rows: " & e.RecordsAffected.ToString() & vbCrLf)

End Sub

Private Sub menuUpdateBatch_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) _

Handles UpdateBatchToolStripMenuItem.Click

Dim nw = ConfigurationManager.ConnectionStrings("nw")

Dim connection = New SqlConnection()

connection.ConnectionString = nw.ConnectionString

Dim cmd = connection.CreateCommand()

cmd.CommandType = CommandType.Text

cmd.CommandText = "SELECT * FROM Customers"

Dim nwSet As New DataSet("nw")

da.SelectCommand = cmd

Dim bldr As New SqlCommandBuilder(da)

da.Fill(nwSet, "Customers")

'chỉnh sửa dữ liệu (viết hoa tên công ty)

For Each dr As DataRow In nwSet.Tables("Customers").Rows

dr("CompanyName") = dr("CompanyName").ToString().ToUpper()

Next

sb.Clear()

da.UpdateBatchSize = 40

da.Update(nwSet, "Customers")

MessageBox.Show(sb.ToString())

End Sub

Mã C#

private SqlDataAdapter da = new SqlDataAdapter();

private System.Text.StringBuilder sb = new System.Text.StringBuilder();

private void rowUpdated(object sender, SqlRowUpdatedEventArgs e )

{

sb.Append("Rows: " + e.RecordsAffected.ToString() + "\r\n");

}

private void menuUpdateBatch_Click(object sender, EventArgs e)

{

da.RowUpdated += rowUpdated;

var nw = ConfigurationManager.ConnectionStrings["nw"];

var connection = new SqlConnection();

connection.ConnectionString = nw.ConnectionString;

var cmd = connection.CreateCommand();

cmd.CommandType = CommandType.Text;

cmd.CommandText = "SELECT * FROM Customers";

da.SelectCommand = cmd;

var nwSet = new DataSet("nw");

var bldr = new SqlCommandBuilder(da);

da.Fill(nwSet, "Customers");

<strong>   </strong> //chỉnh sửa dữ liệu (viết hoa tên công ty)

foreach (DataRow dr in nwSet.Tables["Customers"].Rows)

{

dr["CompanyName"] = dr["CompanyName"].ToString().ToUpper();

}

sb.Clear();

da.UpdateBatchSize = 40;

da.Update(nwSet, "Customers");

da.RowUpdated -= rowUpdated;

MessageBox.Show(sb.ToString());

}

Các lớp DbProviderFactory

Các ứng dụng có thể được viết độc lập với nhà cung cấp để có thể dễ dàng chuyển đổi giữa các nhà cung cấp (như từ MS Access sang MS SQL Server) hay có thể kết nối dễ dàng với nhiều nguồn dữ liệu của các nhà cung cấp khác nhau. Cách phổ biến thường dùng khi viết chương trình có thể như các đoạn mã sau:

Mã VB:


Public Enum DbProvider

SqlClient

OleDb

Odbc

End Enum

Public Function GetConnection() As IDbConnection

' lấy thông tin nhà cung cấp từ tập tin cấu hình

Dim provider As DbProvider = [Enum].Parse( _

GetType(DbProvider), _

ConfigurationSettings.AppSettings("provider").ToString())

Dim connection As IDbConnection = Nothing

Select Case (provider)

Case DbProvider.SqlClient

connection = New System.Data.SqlClient.SqlConnection()

Case DbProvider.OleDb

connection = New System.Data.OleDb.OleDbConnection()

Case DbProvider.Odbc

connection = New System.Data.Odbc.OdbcConnection()

Case DbProvider.Oracle

connection = New System.Data.OracleClient.OracleConnection()

End Select

Return connection

End Function

Mã C#:


public IDbConnection GetConnection()

{

// lấy thông tin nhà cung cấp từ tập tin cấu hình

DbProvider provider = (DbProvider)Enum.Parse(

typeof(DbProvider),

(string)ConfigurationManager.AppSettings["provider"]);

IDbConnection connection = null;

switch (provider)

{

case DbProvider.SqlClient:

connection = new System.Data.SqlClient.SqlConnection();

break;

case DbProvider.OleDb:

connection = new System.Data.OleDb.OleDbConnection();

break;

case DbProvider.Odbc:

connection = new System.Data.Odbc.OdbcConnection();

break;

case DbProvider.Oracle:

connection = new System.Data.OracleClient.OracleConnection();

break;

}

return connection;

}

public enum DbProvider

{ SqlClient, OleDb, Odbc, Oracle };

App.config


<configuration>

<appSettings>

<add key="provider" value="SqlClient" />

</appSettings>

</configuration>

Một số vấn đề:

  • Không thể tạo các thể hiện giao diện một cách trực tiếp vì mỗi nhà cung cấp cụ thể có mã để quyết định kiểu kết nối được tạo.
  • Các giao diện được định nghĩa bất biến (immutable) nên việc thêm các đặc trưng mới là rất khó khăn.

Giải pháp:

Mỗi nhà cung cấp phải cung cấp một lớp con (subclass) của lớp DbProviderFactory để tạo các thể hiện. Ví dụ, chúng ta có thể dùng lớp SqlClientFactory (thừa kế từ DbProviderFactory) để tạo các thể hiện của bất kỳ lớp nào của nhà cung cấp SQL Server.

Mỗi lớp provider factory (ví dụ SqlClientFactory) sẽ cung cấp một thuộc tính instance cho phép truy cập đến các phương thức và thuộc tính. Ví dụ dùng lớp SqlClientFactory để tạo ra kết nối mới như sau:

Mã VB:


Dim factory As DbProviderFactory = SqlClientFactory.Instance

Public Function GetProviderConnection() As DbConnection

Dim connection = factory.CreateConnection()

connection.ConnectionString = "Data Source=.\SQLEXPRESS;" _

& "AttachDbFilename=|DataDirectory|PUBS.MDF;" _

& "Integrated Security=True;User Instance=True"

Return connection

End Function

Mã C#:


DbProviderFactory factory = SqlClientFactory.Instance;

public DbConnection GetProviderConnection()

{

var connection = factory.CreateConnection();

connection.ConnectionString = @"Data Source=.\SQLEXPRESS;"

+ "AttachDbFilename=|DataDirectory|Northwind.MDF;"

+ "Integrated Security=True;User Instance=True";

return connection;

}

Biến factory ở ví dụ trên có thể được dùng để tạo ra các đối tượng SQL Server khác như đoạn mã sau (chú ý SqlDataReader được tạo một cách gián tiếp bằng cách tạo một SQL command và  dùng phương thức ExecuteReader):

Mã VB


Private Function GetData(ByVal commandText As String, _

ByVal commandType As CommandType) As DataTable

'get SqlDbCommand

Dim command = factory.CreateCommand()

command.Connection = GetProviderConnection()

If (command.Connection Is Nothing) Then

Return Nothing

End If

command.CommandText = commandText

command.CommandType = commandType

command.Connection.Open()

Dim dataTable = New DataTable()

'Get SqlDataReader and populate data table

dataTable.Load(command.ExecuteReader())

command.Connection.Close()

Return dataTable

End Function

Mã C#


private DataTable GetData(string commandText, CommandType commandType)

{

//get SqlDbCommand

var command = factory.CreateCommand();

command.Connection = GetProviderConnection();

if (command.Connection == null) return null;

command.CommandText = commandText;

command.CommandType = commandType;

command.Connection.Open();

var dataTable = new DataTable();

//Get SqlDataReader and populate data table

dataTable.Load(command.ExecuteReader());

command.Connection.Close();

return dataTable;

}

Lớp DbException

Các ngoại lệ phát sinh khi từ các provider sẽ được thừa kế từ lớp cơ sở DbException. Khối try/catch sẽ đón bắt DbException thay vì đón bắt các ngoại lệ của từng nhà cung cấp cụ thể.