避免字串拼接 SQL 的痛苦:參數處理、引號、逗號、WHERE 條件組裝。`BuildQuery` 類封裝欄位/值/引號/運算子,支援 `INSERT`/`UPDATE`/`DELETE` 三大操作,可重複使用 (Flush 機制),輸出參數化就緒的 SQL 字串 (仍需配合參數化執行防注入)。
public class BuildQuery
{
#region Fields
private readonly Dictionary _fields = new(); // 欄位名 -> 欄位名 (保持順序)
private readonly Dictionary _data = new(); // 欄位名 -> 值
private readonly Dictionary _quotes = new(); // 欄位名 -> 是否加引號
private readonly List _idFields = new(); // WHERE 條件欄位
private readonly List _idValues = new(); // WHERE 條件值
private readonly List _idQuotes = new(); // WHERE 條件引號
private readonly List _idOperators = new(); // WHERE 條件運算子
private string _table;
private bool _getIdentity;
#endregion
#region Properties
public string Table { get => _table; set => _table = value; }
public bool GetIdentity { get => _getIdentity; set => _getIdentity = value; }
#endregion
#region Public Methods
public void FlushAllData() {
_fields.Clear(); _data.Clear(); _quotes.Clear();
_idFields.Clear(); _idValues.Clear(); _idQuotes.Clear(); _idOperators.Clear();
}
/// 加入 SET/VALUES 欄位與值
public void Build(string field, string value, bool quotes) {
if (!_fields.ContainsKey(field)) _fields[field] = field;
_data[field] = value;
_quotes[field] = quotes;
}
/// 加入 WHERE 條件 (預設 =)
public void IDSettings(string field, string value, bool quotes)
=> IDSettings(field, value, quotes, "=");
/// 加入 WHERE 條件 (自訂運算子)
public void IDSettings(string field, string value, bool quotes, string op) {
_idFields.Add(field); _idValues.Add(value); _idQuotes.Add(quotes); _idOperators.Add(op);
}
public string Insert() {
if (string.IsNullOrEmpty(_table)) return "ERROR: Table not set";
var sb = new StringBuilder($"INSERT INTO {_table} (");
int i = 0, n = _data.Count;
foreach (var kv in _fields) {
sb.Append(kv.Value); if (++i < n) sb.Append(", ");
}
sb.Append(") VALUES (");
i = 0;
foreach (var kv in _data) {
if (_quotes[kv.Key]) sb.Append("'");
sb.Append(kv.Value);
if (_quotes[kv.Key]) sb.Append("'");
if (++i < n) sb.Append(", ");
}
sb.Append(")");
if (_getIdentity) sb.Append("; SELECT SCOPE_IDENTITY() AS NewId;");
return sb.ToString();
}
public string Update() {
if (string.IsNullOrEmpty(_table)) return "ERROR: Table not set";
var sb = new StringBuilder($"UPDATE {_table} SET ");
int i = 0, n = _data.Count;
foreach (var kv in _fields) {
sb.Append($"{kv.Value} = ");
if (_quotes[kv.Key]) sb.Append("'");
sb.Append(_data[kv.Key]);
if (_quotes[kv.Key]) sb.Append("'");
if (++i < n) sb.Append(", ");
}
if (_idFields.Count > 0) {
sb.Append(" WHERE ");
for (int j = 0; j < _idFields.Count; j++) {
if (j > 0) sb.Append(" AND ");
sb.Append($"{_idFields[j]} {_idOperators[j]} ");
if (_idQuotes[j]) sb.Append("'");
sb.Append(_idValues[j]);
if (_idQuotes[j]) sb.Append("'");
}
}
return sb.ToString();
}
public string Delete() {
if (string.IsNullOrEmpty(_table)) return "ERROR: Table not set";
var sb = new StringBuilder($"DELETE FROM {_table} WHERE ");
for (int j = 0; j < _idFields.Count; j++) {
if (j > 0) sb.Append(" AND ");
sb.Append($"{_idFields[j]} {_idOperators[j]} ");
if (_idQuotes[j]) sb.Append("'");
sb.Append(_idValues[j]);
if (_idQuotes[j]) sb.Append("'");
}
return sb.ToString();
}
#endregion
}
var q = new BuildQuery { Table = "Users", GetIdentity = true };
q.Build("Name", "John Smith", true);
q.Build("Age", "30", false);
q.Build("Email", "john@example.com", true);
string sql = q.Insert();
// INSERT INTO Users (Name, Age, Email) VALUES ('John Smith', 30, 'john@example.com'); SELECT SCOPE_IDENTITY() AS NewId;
q.FlushAllData(); // 重用物件
q.Table = "Users";
q.IDSettings("Id", "123", false);
q.Build("Name", "John Updated", true);
q.Build("Age", "31", false);
string sql = q.Update();
// UPDATE Users SET Name = 'John Updated', Age = 31 WHERE Id = 123
q.Table = "Users";
q.IDSettings("Id", "123", false);
q.IDSettings("IsActive", "0", false, "<>"); // 自訂運算子
string sql = q.Delete();
// DELETE FROM Users WHERE Id = 123 AND IsActive <> 0
`BuildQuery` 以字典+列表輕量封裝 SQL 建構細節,解決「引號、逗號、AND、WHERE」的重複勞動,適合中小型專案、動態報表、遷移腳本快速生成 SQL。核心價值:**關注點分離** (業務邏輯 vs SQL 語法)、**可重用物件** (Flush 機制)、**可擴充架構**。生產核心系統仍建議使用成熟 ORM (EF Core, Dapper) 或預存程序。