.NET 資料提供者在應用程式與資料源間扮演橋樑。為達最佳效能,**務必選用針對特定資料源優化的提供者**:
| 資料源 | 推薦提供者 | 命名空間 |
|---|---|---|
| SQL Server 7.0+ | SQL Server .NET 資料提供者 | System.Data.SqlClient |
| OLE DB | OLE DB .NET 資料提供者 | System.Data.OleDb |
| ODBC | ODBC .NET 資料提供者 | System.Data.Odbc |
| Oracle | Oracle .NET 資料提供者 | System.Data.OracleClient / ODP.NET |
SQL Server 提供者直接存取 TDS 協定,無額外轉換層,效能最佳。
注意: DataAdapter.Fill 內部使用 DataReader,改用 DataAdapter 節省的記憶體與迴圈開銷通常屬象徵性,決策應以功能需求為主。
Customer.Name 而非 row["Name"])XSD 結構描述中設定 nullValue:
String.Empty 替代// 依主鍵合並更新現有列,RowState 變 Unchanged
dataAdapter.Fill(dataSet);
// 保留本地修改同時刷新
dataAdapter.Fill(newDataTable);
dataSet.Merge(newDataTable, true); // preserveChanges = true
DataTable.Rows.Find(key) (使用索引) 優於 Select()DataView 設定 Sort 建立索引,使用 Find/FindRowsSelect()// 佳:建構子一次指定 Sort/Filter,建立一次索引
var view = new DataView(table, "Column > 5", "Column DESC", DataViewRowState.CurrentRows);
// 避免:建立空 View 後再設定屬性,導致多次建立索引
var view = new DataView(table);
view.Sort = "Column DESC"; // 觸發第二次索引建立
// 不佳:仍傳回完整結果集,浪費資源
da.Fill(ds, startRecord, maxRecords, "Table");
// 下一頁
SELECT TOP 10 * FROM Customers WHERE Id > @LastId ORDER BY Id ASC
// 上一頁
SELECT TOP 10 * FROM Customers WHERE Id < @FirstId ORDER BY Id DESC
-- 第 3 頁,頁面大小 10
SELECT TOP 10 * FROM
(SELECT TOP 30 * FROM Customers ORDER BY Id ASC) AS T
ORDER BY Id DESC
資料不常變動時,DataSet 快取 10 頁資料,超出範圍再查詢新資料。
da.MissingSchemaAction = MissingSchemaAction.AddWithKey;
// 或預先呼叫
da.FillSchema(ds, SchemaType.Source);
包含主鍵、唯一約束、允許空值、最大長度、唯讀、自動遞增等結構描述資訊。預先指定結構描述可避免額外往返伺服器。
SelectCommand 變更後需呼叫 RefreshSchema()多條命令合併單次往返 (SQL Server 用分號分隔) 可減少網路延遲:
-- 本地累積刪除命令,批次送出
DELETE FROM Orders WHERE Id = 1; DELETE FROM Orders WHERE Id = 2;
但會增加 DataSet 更新管理複雜度,建議每個 DataTable 對應一個 DataAdapter 保持簡單。
da.Fill(ds, "Customers");
第一個表命名為 "Customers",後續表自動命名 "Customers1"、"Customers2"... 需手動對應:
da.TableMappings.Add("Customers1", "Orders");
GetString, GetInt32) 避免裝箱轉型CommandBehavior.SequentialAccess:按需載入欄位,大幅降低 BLOB 記憶體佔用Command.Cancel() 放棄結果流var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess);
// 必須按順序讀取欄位,BLOB 使用 GetBytes/GetChars 分塊讀取
CommandType.Text)CommandType.StoredProcedure,避免解析開銷參數化命令重複執行時,Prepare() 通知資料源優化。SQL Server 2000+ 隱式優化無需呼叫,SQL Server 7.0 有效。
避免 Fill、CommandBuilder、DeriveParameters 推斷中繼資料的效能損耗,生產環境應顯式定義。
COUNT(*), SUM()) 用 ExecuteScalar,單步完成ExecuteNonQuery,避免建立空 DataReaderparam.Value = DBNull.Value; // 而非 null/Nothing
WHERE (LastName = @LastName) OR (LastName IS NULL AND @LastName IS NULL)
ADO.NET 交易模型:**顯式關聯 Command 與 Transaction**
conn.Open();
var trans = conn.BeginTransaction();
cmd.Transaction = trans;
try {
da.Update(ds);
trans.Commit();
} catch {
trans.Rollback();
} finally {
conn.Close();
}
未關聯 Transaction 的 Command 會擲出例外。分散式交易需 .NET 2.0+ TransactionScope。
Open/Closeusing 區塊 (C#) 確保 Dispose 呼叫// C# using 範例
using (var conn = new SqlConnection(connString))
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "SELECT ...";
conn.Open();
using (var dr = cmd.ExecuteReader())
{
while (dr.Read()) Console.WriteLine("{0}\t{1}", dr.GetString(0), dr.GetString(1));
}
}
DataSet 深度整合 XML:
XmlDataDocument 同步關聯/階層檢視,支援 XPath/XSLTFOR XML 查詢搭配 SqlCommand.ExecuteXmlReaderMicrosoft.Data.SqlXml) 支援 XPath、XSLT、XML 模板AutoIncrementStep = -1, AutoIncrementSeed = 0 產生負數 IDTimestamp 欄位需 ADOMD 等 ADO 獨有功能時才使用,效能較差。