在企業級應用開發中,Windows Forms 仍是常見的桌面應用框架。本文將詳細解析一個完整的「新增功能」表單實作,涵蓋 UI 設計、資料驗證、Oracle 資料庫操作(含序列取號與交易控制)等核心技術點。程式碼出自真實專案 SM_AddNewFunction,展示如何將使用者輸入寫入「功能」資料表。
表單繼承 System.Windows.Forms.Form,在 InitializeComponent 中宣告所有控制項:
txt_Name)、標識 (txt_Tag)、功能體 (txt_FunEntity)、所屬視窗標識 (txt_BelongTo)、描述 (txt_Detail)cbo_Type),資料來源為 ClientDictionary[] 陣列,設定 ValueMember 與 DisplayMemberckb_IsInterface)btn_Confirm)、取消 (btn_Cancel)、說明 (btn_Help)建構子接收 fatherID(上層功能 ID)與 dic_funcType(類別字典),初始化 newFuncItem 並建立 Oracle 連線。
private void btn_Confirm_Click(object sender, EventArgs e)
{
// 1. 必填欄位驗證
if (string.IsNullOrEmpty(txt_Name.Text)) { MessageBox.Show("功能名稱不能為空"); return; }
if (string.IsNullOrEmpty(txt_Tag.Text)) { MessageBox.Show("功能標識不能為空"); return; }
if (string.IsNullOrEmpty(txt_FunEntity.Text)) { MessageBox.Show("功能體不能為空"); return; }
// 2. 組裝實體物件
newFuncItem.funcName = txt_Name.Text.Trim();
newFuncItem.funcTag = txt_Tag.Text.Trim();
newFuncItem.funcIsInterface = ckb_IsInterface.Checked ? "1" : "0";
newFuncItem.funcID = QueryNextFuncID(); // 取得序列號
if (newFuncItem.funcID == 0) return; // 取號失敗則中止
newFuncItem.funcType = cbo_Type.SelectedValue.ToString().Trim();
newFuncItem.funcEntity = txt_FunEntity.Text.Trim();
newFuncItem.funcBelongTo = txt_BelongTo.Text.Trim();
newFuncItem.funcDetail = txt_Detail.Text.Trim();
newFuncItem.funcIsExpand = "";
newFuncItem.funcVer = "";
// 3. 執行新增
InsertFuncItem(newFuncItem);
this.Close();
}
private long QueryNextFuncID()
{
long nextID = 0;
try
{
funcTableConn.Open();
using (var cmd = new OracleCommand("select SEQ_功能.nextval from dual", funcTableConn))
using (var reader = cmd.ExecuteReader())
{
if (reader.Read()) nextID = reader.GetInt64(0);
}
}
catch (Exception ex) { MessageBox.Show("查詢時出現錯誤:" + ex); }
finally { funcTableConn.Close(); }
return nextID;
}
private void InsertFuncItem(FunctionTable newItem)
{
funcTableConn.Open();
using (var tran = funcTableConn.BeginTransaction())
{
try
{
var sql = @"INSERT INTO 功能 (功能ID,功能標識,功能名稱,功能簡述,所屬窗體,有無界面,功能類別,功能體,上級功能ID,可否展顯,版本號)
VALUES (:id,:tag,:name,:detail,:belong,:interface,:type,:entity,:father,:expand,:ver)";
using (var cmd = new OracleCommand(sql, funcTableConn, tran))
{
cmd.Parameters.Add("id", newItem.funcID);
cmd.Parameters.Add("tag", newItem.funcTag);
cmd.Parameters.Add("name", newItem.funcName);
cmd.Parameters.Add("detail", newItem.funcDetail);
cmd.Parameters.Add("belong", newItem.funcBelongTo);
cmd.Parameters.Add("interface", newItem.funcIsInterface);
cmd.Parameters.Add("type", newItem.funcType);
cmd.Parameters.Add("entity", newItem.funcEntity);
cmd.Parameters.Add("father", newItem.funcFatherID);
cmd.Parameters.Add("expand", newItem.funcIsExpand);
cmd.Parameters.Add("ver", newItem.funcVer);
cmd.ExecuteNonQuery();
}
tran.Commit();
}
catch (Exception ex)
{
try { tran.Rollback(); } catch { /* ignore rollback error */ }
MessageBox.Show("新增失敗:" + ex.Message);
}
finally { funcTableConn.Close(); }
}
}
重點:使用參數化查詢防止 SQL Injection,交易確保資料一致性。
private void btn_Cancel_Click(object sender, EventArgs e)
{
newFuncItem.funcID = -1; // 標記為未新增
this.Close();
}
此範例展示了傳統 Windows Forms 開發的完整流程:表單設計、輸入驗證、實體映射、資料庫序列取號、參數化 SQL 執行與交易處理。雖然技術棧較舊,但核心觀念(資料驗證、交易控制、資源釋放)在現代開發中依然適用。