Table of Contents

SQL - Basic Usage

SQL 類別封裝了 SQL Server 的常見操作 — 連線、查詢、預存程序、Bulk Copy、Transaction — 並提供 QuickXxx 系列方法,幫你自動處理「開連線 → 執行 → 關連線」的樣板程式碼。

Namespace

using ZapLib;

Initialize

SQL 提供三種建構子,依使用情境選擇即可:

從 .config 自動讀取連線資訊

如果 App.config / Web.config 中已寫好 DBHostDBNameDBActDBPwd,可不傳任何參數:

<appSettings>
  <add key="DBHost" value="10.0.0.1" />
  <add key="DBName" value="MyDatabase" />
  <add key="DBAct"  value="sa" />
  <add key="DBPwd"  value="P@ssw0rd" />
</appSettings>
SQL db = new SQL();

直接傳入連線資訊

SQL db = new SQL(
    dbHost: "10.0.0.1",
    dbName: "MyDatabase",
    dbAct:  "sa",
    dbPwd:  "P@ssw0rd"
);

從 connectionStrings 或完整連線字串

<connectionStrings>
  <add name="DefaultConn"
       connectionString="Server=10.0.0.1;Database=MyDatabase;User ID=sa;Password=P@ssw0rd" />
</connectionStrings>
// 以名稱
SQL db = new SQL("DefaultConn");

// 或直接給字串
SQL db2 = new SQL("Server=10.0.0.1;Database=MyDatabase;User ID=sa;Password=P@ssw0rd");

Sample Schema

以下章節的範例都以這張 Book 表為例:

id name since
1 程式設計寶典 1999-01-01 00:00:00
2 大家都來寫程式 1999-01-01 00:00:00

Declare Data Model

定義一個能夠承接資料的模型類別,屬性名稱需與資料表欄位對齊(不分大小寫):

public class ModelBook
{
    public int id { get; set; }
    public string name { get; set; }
    public DateTime since { get; set; }
}

Get All Data

QuickQuery<T> 會自動開連線、執行、把結果倒進 T[]、最後關連線。這是最常用的查詢方法。

SQL db = new SQL("DefaultConn");

ModelBook[] books = db.QuickQuery<ModelBook>("SELECT * FROM Book");

foreach (var book in books)
{
    Console.WriteLine($"{book.id} {book.name} {book.since:yyyy-MM-dd}");
}

輸出:

1 程式設計寶典 1999-01-01
2 大家都來寫程式 1999-01-01

Get One Row

只想拿第一筆?把第三個參數 isfetchall 設成 false

ModelBook[] result = db.QuickQuery<ModelBook>("SELECT * FROM Book", null, isfetchall: false);
ModelBook book = result[0];

Parameterized Query

絕對不要用字串拼接 SQLQuickQuery<T> 的第二個參數接受匿名物件,屬性名對應 SQL 中的 @param

ModelBook[] books = db.QuickQuery<ModelBook>(
    "SELECT * FROM Book WHERE id = @id AND since >= @from",
    new {
        id = 1,
        from = new DateTime(1999, 1, 1)
    }
);

IN Clause with Arrays

C# 的 SqlCommand.Parameters 預設不支援陣列展開IN (...)。ZapLib 提供 ExpParam 解決:

int[] ids = new[] { 1, 5, 10 };

ModelBook[] books = db.QuickQuery<ModelBook>(
    "SELECT * FROM Book WHERE id IN (@ids)",
    new { ids = new ExpParam(ids) }
);
// 實際 SQL:SELECT * FROM Book WHERE id IN (@ids0, @ids1, @ids2)

詳見 SQL / ExpParam

Get Without Model — Dynamic

懶得宣告 model?用 QuickDynamicQuerydynamic[]

dynamic[] rows = db.QuickDynamicQuery("SELECT id, name FROM Book");

foreach (var row in rows)
{
    Console.WriteLine($"{row.id} {row.name}");
}

何時用哪一個? 真實專案建議用 QuickQuery<T> — 有型別檢查、IDE 補全友善。QuickDynamicQuery 適合一次性腳本或欄位會浮動的查詢。

Error Handling

QuickXxx 方法在失敗時不會 throw,而是回傳 null。錯誤訊息可從 GetErrorMessage() 取得:

ModelBook[] books = db.QuickQuery<ModelBook>("SELECT * FROM NotExistTable");

if (books == null)
{
    Console.WriteLine("查詢失敗:" + db.GetErrorMessage());
}

輸出:

查詢失敗:SQL Error:SELECT * FROM NotExistTable para:null
System.Data.SqlClient.SqlException: Invalid object name 'NotExistTable'.
   at ...

Connection Options

SQL 物件建構後、第一次連線前,可調整下列屬性:

屬性 預設 說明
Timeout 30 連線逾時秒數
Encrypt false 是否使用 SSL 加密傳輸
TrustServerCertificate false 是否信任伺服器憑證
MultiSubnetFailover false 跨子網路的可用性群組
ApplicationIntent "ReadWrite" 工作負載類型
EnableDBAlwaysOn false 啟用 AlwaysOn 唯讀路由

範例:

SQL db = new SQL("DefaultConn");
db.Timeout = 60;
db.Encrypt = true;
db.TrustServerCertificate = true;

ModelBook[] books = db.QuickQuery<ModelBook>("SELECT * FROM Book");

What's Next