以「使用者登入驗證」為例:輸入帳號、密碼、權限,預存程序回傳符合條件的資料筆數(0 或 1)作為輸出參數,C# 呼叫後據以判斷登入成敗。
USE [Hotel]
GO
IF EXISTS (SELECT * FROM sysobjects WHERE name = 'proc_userinfo')
DROP PROC proc_userinfo
GO
CREATE PROC proc_userinfo
@username VARCHAR(50), -- 輸入參數
@pwd VARCHAR(50), -- 輸入參數
@grade VARCHAR(20), -- 輸入參數
@count INT OUTPUT -- 輸出參數,關鍵字 OUTPUT 不可少
AS
SELECT @count = COUNT(*)
FROM userinfo
WHERE username = @username AND pwd = @pwd AND grade = @grade
GO
-- 測試執行
DECLARE @n INT
EXEC proc_userinfo 'admin', '123', '管理員', @n OUTPUT
PRINT @n
using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
public class UserRepository
{
private readonly string _connString = ConfigurationManager.ConnectionStrings["connString"].ConnectionString;
///
/// 驗證使用者帳密權限,回傳是否存在符合記錄
///
public bool ValidateUser(string username, string pwd, string grade)
{
using (var conn = new SqlConnection(_connString))
using (var cmd = new SqlCommand("proc_userinfo", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
// 輸入參數
cmd.Parameters.Add("@username", SqlDbType.VarChar, 50).Value = username;
cmd.Parameters.Add("@pwd", SqlDbType.VarChar, 50).Value = pwd;
cmd.Parameters.Add("@grade", SqlDbType.VarChar, 20).Value = grade;
// 輸出參數:Direction 必須設為 Output
var outParam = cmd.Parameters.Add("@count", SqlDbType.Int);
outParam.Direction = ParameterDirection.Output;
conn.Open();
cmd.ExecuteNonQuery(); // 或 ExecuteScalar(),這裡不需回傳結果集
int count = (int)outParam.Value;
return count == 1;
}
}
}
| 細節 | 說明 |
|---|---|
CommandType.StoredProcedure | 告知 ADO.NET 執行的是預存程序而非 T-SQL 字串 |
ParameterDirection.Output | 標記該參數為輸出,執行後才能讀取 .Value |
using 區塊 | 確保連線與命令物件在離開範圍時立即釋放,避免連線洩漏 |
參數名稱前綴 @ | SQL Server 參數慣例,ADO.NET 會自動對應 |
// Service 層
public class AuthService
{
private readonly UserRepository _repo = new UserRepository();
public bool Login(string user, string pwd, string grade) => _repo.ValidateUser(user, pwd, grade);
}
// UI 層 (WinForms 範例)
private void btnLogin_Click(object sender, EventArgs e)
{
var svc = new AuthService();
if (svc.Login(txtUser.Text, txtPwd.Text, cboGrade.Text))
MessageBox.Show("登入成功");
else
MessageBox.Show("帳號、密碼或權限錯誤");
}
// 正確做法:操作資料來源而非直接清除 Rows
if (dataGridView1.DataSource is DataTable dt)
{
dt.Rows.Clear(); // 清除所有資料列
// dataGridView1.DataSource = dt; // 不需重新指派,UI 會自動重新整理
}
掌握 SqlParameter.Direction 與 CommandType.StoredProcedure,即可在 C# 中靈活呼叫帶輸出參數的預存程序,配合 using 確保資源釋放,是資料存取層的基本功夫。