C# · SQL Server · ASP.NET MVC · JavaScript

語法速查表

忘了就查。搜尋框打關鍵字即時過濾(中英都可),程式碼右上角可一鍵複製。

沒有符合的項目,換個關鍵字試試。

C# 常用集合

你筆記裡的弱點——用就熟,不是背

List<T> 動態陣列 最常用

var list = new List<int>();
list.Add(5);              // 加
list.Remove(5);           // 移除值
list.RemoveAt(0);         // 移除索引
int n = list.Count;        // 數量(不是 Length)
bool has = list.Contains(5);
foreach (var x in list) { }

Dictionary<K,V> 鍵值對 查詢 O(1)

var map = new Dictionary<string,int>();
map["a"] = 1;             // 加 / 改
if (map.ContainsKey("a")) { }   // 先查再用
if (map.TryGetValue("a", out var v)) { } // 更安全
map.Remove("a");
foreach (var kv in map) { var k=kv.Key; var val=kv.Value; }
Two Sum 心法:map 存「值→索引」,先 ContainsKey 再存,一輪 O(n) 用空間換時間。

HashSet<T> 不重複集合 去重/查存在

var set = new HashSet<int>();
set.Add(1);               // 重複加不會錯,回傳 false
bool has = set.Contains(1);   // O(1) 查存在
set.Remove(1);

Stack / Queue 堆疊 / 佇列 LIFO / FIFO

var st = new Stack<int>();   // 後進先出
st.Push(1); int top = st.Pop(); int peek = st.Peek();

var q = new Queue<int>();    // 先進先出
q.Enqueue(1); int first = q.Dequeue(); int pk = q.Peek();

陣列 vs new 語法

int[] arr = new int[5];        // 固定長度 5,預設 0
int[] arr2 = { 1, 2, 3 };       // 直接給值
int len = arr.Length;          // 陣列用 Length(List 用 Count)
int[,] grid = new int[3,3];   // 二維

C# 常用語法

null 處理、string、async/await

null 安全:?. 與 ??

var name = user?.Name ?? "訪客";
// user 為 null → 整段不爆,回 "訪客"
// ?.  null 條件:是 null 就停,回 null
// ??  null 合併:左邊 null 就取右邊
user?.DoSomething();      // null 就不呼叫,不報錯
list ??= new();          // 是 null 才指派

string 是不可變的

string s = "abc";
s = s + "d";             // 產生新字串,不是改原本
// 大量字串相接 → 用 StringBuilder
var sb = new StringBuilder();
sb.Append("x"); string r = sb.ToString();
string msg = $"Hi {name}, {count} 筆";  // 字串插值

async / await

public async Task<User> GetAsync(int id)
{
    var u = await _db.Users.FirstOrDefaultAsync(x => x.Id == id);
    return u;
}
口說重點:async 標記非同步、回傳 Task/Task<T>;await 等待但不阻塞 thread,等待期間 thread 還給 pool,server 可處理別的 request。不一定開新 thread。

存取修飾詞

修飾詞誰能存取
public任何地方
private只有這個 class 內
protected這個 class + 繼承它的子類別
internal同一個專案(組件)內

value type vs reference type

int/bool/double/struct = 傳值(複本,改了不影響外面);string/陣列/class/物件 = 傳參考(指向同一份)。

LINQ 速查

5 秒說出「在做什麼、為什麼、有沒有限制」

常用方法

list.Where(x => x.Age > 18)        // 過濾(等於 SQL WHERE)
    .Select(x => x.Name)            // 投影:只取需要的欄位
    .OrderBy(x => x.Age)            // 排序(降冪 OrderByDescending)
    .ToList();

list.FirstOrDefault(x => x.Id==1)  // 第一個,沒有回 null(不報錯)
list.Any(x => x.Active)            // 有沒有符合的,回 bool(比 Count>0 快)
list.Count(x => x.Active)          // 數符合的
list.GroupBy(x => x.City)          // 分組
list.Sum(x => x.Fee)              // 加總

EF:Include 與動態 Where

// Include = JOIN,把關聯資料一起撈,省第二次查詢
_db.Orders.Include(o => o.Details)

// IQueryable 動態疊加:條件不固定時只發一次 SQL
var q = _db.Users.AsQueryable();
if (active) q = q.Where(u => u.Active);
var result = await q.ToListAsync();
記憶體 vs DB:List 上的 .Where() 是 C# 在記憶體跑;IQueryable 上的會翻成 SQL 丟資料庫。

SQL Server 速查

JOIN 與 COUNT 陷阱——你連續卡過三次,必看

JOIN 三表關聯

SELECT A.*
FROM 顧客 A
JOIN 關聯 C ON A.顧客ID = C.顧客ID
JOIN 商店 B ON C.商店ID = B.商店ID
WHERE B.商店名稱 = '某商店';
JOIN意思
INNER JOIN兩邊都有才出現(預設)
LEFT JOIN左表全保留,右表沒有補 NULL

找「沒有對應的」資料

-- 找沒有員工的部門
SELECT d.name
FROM departments d
LEFT JOIN employees e ON d.id = e.dept_id
WHERE e.id IS NULL;
COUNT 陷阱(連卡三次):要數「被 LEFT JOIN 補 NULL 的那張表」的欄位 → COUNT(e.id),不要 COUNT(*)COUNT(d.id)(會把沒員工的算成 1)。

GROUP BY / HAVING / 聚合

SELECT dept_id, COUNT(*) AS 人數, AVG(salary) AS 平均
FROM employees
GROUP BY dept_id
HAVING COUNT(*) > 3       -- 分組後過濾用 HAVING(不是 WHERE)
ORDER BY 人數 DESC;
COALESCE:COUNT 沒資料回 0 不用包;SUM/AVG/MAX/MIN 沒資料回 NULL,要 COALESCE(SUM(x),0)

增刪改 (DML)

INSERT INTO t (a,b) VALUES (1,2);
UPDATE t SET a=1 WHERE id=5;   -- 一定要 WHERE!
DELETE FROM t WHERE id=5;       -- 一定要 WHERE!
Transaction 使用時機:多步驟要原子性時(如報名同時更新人數)。做一半失敗 → ROLLBACK,避免資料不一致。

常用篩選與函式

WHERE name LIKE '%王%'        -- 模糊:% 任意, _ 單一
WHERE id IN (1,2,3)
WHERE age BETWEEN 18 AND 30
SELECT TOP 10 * FROM t            -- SQL Server 取前 N 筆
SELECT DISTINCT city FROM t        -- 去重
CASE WHEN age>=18 THEN '成年' ELSE '未成年' END

資料庫連接 / 建表

舊版 ASP.NET 多用 ADO.NET 手寫——前兩週的重頭戲

連線字串放 Web.config

<connectionStrings>
  <add name="DbConn"
    connectionString="Server=主機名;Database=資料庫名;User Id=帳號;Password=密碼;"
    providerName="System.Data.SqlClient" />
</connectionStrings>
<!-- Windows 驗證版:Server=.;Database=DB;Integrated Security=True; -->
程式裡取用:ConfigurationManager.ConnectionStrings["DbConn"].ConnectionString(需 using System.Configuration;)。密碼別寫死在程式碼。

ADO.NET 標準流程 最常用

using System.Data.SqlClient;

string cs = ConfigurationManager.ConnectionStrings["DbConn"].ConnectionString;
using (var conn = new SqlConnection(cs))
{
    conn.Open();
    string sql = "SELECT Id, Name FROM Users WHERE Age > @age";
    using (var cmd = new SqlCommand(sql, conn))
    {
        cmd.Parameters.AddWithValue("@age", 18);   // 參數化!
        using (var rd = cmd.ExecuteReader())
        {
            while (rd.Read())
            {
                int id = (int)rd["Id"];
                string name = rd["Name"].ToString();
            }
        }
    }
}  // using 自動關連線,不會洩漏
三種執行方式:ExecuteReader() 讀多筆 → ExecuteScalar() 取單一值(如 COUNT) → ExecuteNonQuery() 做 INSERT/UPDATE/DELETE(回傳影響筆數)。

參數化查詢(防 SQL Injection)必守

// ❌ 絕對不要字串相接(會被注入攻擊)
string bad = "SELECT * FROM Users WHERE Name = '" + input + "'";

// ✅ 一律用參數
cmd.CommandText = "SELECT * FROM Users WHERE Name = @name";
cmd.Parameters.AddWithValue("@name", input);
這是資安底線,面試也常考。看到字串拼 SQL 就要警覺。

INSERT 後取得新 ID

string sql = "INSERT INTO Users(Name) VALUES(@n); SELECT SCOPE_IDENTITY();";
var cmd = new SqlCommand(sql, conn);
cmd.Parameters.AddWithValue("@n", "小明");
int newId = Convert.ToInt32(cmd.ExecuteScalar());  // 拿剛插入的自增 ID

交易 Transaction(ADO.NET)

using (var tx = conn.BeginTransaction())
{
    try {
        var cmd = new SqlCommand(sql, conn, tx);  // 帶入 tx
        cmd.ExecuteNonQuery();
        tx.Commit();    // 全部成功才提交
    } catch {
        tx.Rollback();  // 任一步失敗就全退回
        throw;
    }
}

CREATE TABLE 建表

CREATE TABLE Users (
    Id        INT IDENTITY(1,1) PRIMARY KEY,   -- 自增主鍵
    Name      NVARCHAR(50) NOT NULL,          -- 中文用 N 開頭
    Email     NVARCHAR(100) UNIQUE,
    Age       INT DEFAULT 0,
    DeptId    INT,
    CreatedAt DATETIME DEFAULT GETDATE(),
    FOREIGN KEY (DeptId) REFERENCES Departments(Id)  -- 外鍵
);

SQL Server 常用資料型別

型別用途
INT / BIGINT整數 / 大整數
NVARCHAR(n)變動長字串(支援中文,n=最大長度)
VARCHAR(n)變動長字串(僅英數)
DECIMAL(18,2)精確小數(金額用,總18位、小數2位)
BIT布林(0/1)
DATETIME / DATE日期時間 / 只有日期
金額別用 float/real(有誤差),用 DECIMAL。存中文欄位用 NVARCHAR 不是 VARCHAR

ALTER TABLE 改表

ALTER TABLE Users ADD Phone NVARCHAR(20);        -- 加欄位
ALTER TABLE Users DROP COLUMN Phone;             -- 刪欄位
ALTER TABLE Users ALTER COLUMN Name NVARCHAR(100); -- 改型別
CREATE INDEX IX_Users_Name ON Users(Name);       -- 建索引(查詢加速)
DROP TABLE Users;                                  -- 刪整張表(小心!)

── Entity Framework 版本 ── EF6 / Core 通用

若公司用 EF(舊版多是 EF6),就不用手寫 SQL,改用 DbContext + LINQ。語法 EF6 與 EF Core 大致相同,差異標註在下方。

DbContext 與連線 EF

public class AppDbContext : DbContext
{
    // EF6:建構式傳 Web.config 裡 connectionStrings 的 name
    public AppDbContext() : base("name=DbConn") { }
    public DbSet<User> Users { get; set; }
    public DbSet<Dept> Depts { get; set; }
}
// 用的時候 using 包起來,會自動關
using (var db = new AppDbContext()) { ... }
EF6 vs Core:EF6 建構式傳 "name=DbConn" 對應 Web.config;EF Core 改在 OnConfiguring 或 DI 用 UseSqlServer(...)

CRUD:查 / 增 / 改 / 刪 EF

using (var db = new AppDbContext())
{
    // 查
    var u  = db.Users.Find(1);                       // 用主鍵找
    var u2 = db.Users.FirstOrDefault(x => x.Name=="小明");
    var adults = db.Users.Where(x => x.Age >= 18).ToList();

    // 增
    db.Users.Add(new User { Name = "小華" });

    // 改(先查出來、改屬性)
    u.Name = "新名字";

    // 刪
    db.Users.Remove(u2);

    db.SaveChanges();   // ★ 增改刪都要這行才真正寫進 DB
}
關鍵:Add/Remove/改屬性只是在記憶體記帳,SaveChanges() 才送一次到資料庫。漏掉就不會存。

Include 關聯 + 投影 + async EF

// Include = JOIN,把關聯資料一起撈(省第二次查詢)
var list = db.Users
    .Include(u => u.Dept)                 // 連部門一起帶
    .Where(u => u.Active)
    .Select(u => new { u.Name, Dept = u.Dept.Name })  // 只取需要欄位
    .ToList();

// async 版(EF6 需 using System.Data.Entity;)
var u = await db.Users.FirstOrDefaultAsync(x => x.Id == id);
var all = await db.Users.ToListAsync();
await db.SaveChangesAsync();

ADO.NET vs EF:怎麼選 觀念

ADO.NETEF
SQL自己手寫LINQ 自動翻譯
掌控度高、效能可調方便、開發快
適合複雜查詢、舊系統一般 CRUD
防注入要自己參數化預設參數化
進公司先看現有 code 是哪一種,跟著既有寫法走,別自己另起一套。

ASP.NET MVC 5 速查

舊版 .NET Framework,Controller / Razor 觀念同 Core

Controller Action 回傳型別

public class HomeController : Controller
{
    public ActionResult Index()        => View();              // 回畫面
    public ActionResult List()         => View(model);         // 帶資料
    public JsonResult Api()            => Json(data, JsonRequestBehavior.AllowGet);
    public ActionResult Go()           => RedirectToAction("Index");
    [HttpPost]
    public ActionResult Save(Model m)  { ... }                // 表單自動綁到 m
}
vs Core:Core 用 IActionResult + return Ok()/View();MVC 5 用 ActionResult。Json 在 5 要加 JsonRequestBehavior.AllowGet

Razor 語法 (.cshtml)

@model MyApp.Models.User       @* 宣告 model 型別 *@
<h1>@Model.Name</h1>            @* 輸出變數 *@
@if (Model.Active) { <p>啟用</p> }
@foreach (var x in Model.Items) { <li>@x.Name</li> }
@Html.ActionLink("連結", "Index", "Home")
@Html.TextBoxFor(m => m.Name)  @* 綁 model 的輸入框 *@

舊版 vs Core 對照

項目MVC 5Core
設定檔Web.configappsettings.json
啟動Global.asaxProgram.cs
DIAutofac/Unity內建
部署IIS跨平台/Docker

JavaScript 陷阱

你筆試踩過的——falsy 清單、const、this

falsy 只有 6 個

// falsy: false, 0, "", null, undefined, NaN
// 其他全 truthy!包括:
if ([])      // truthy(空陣列)
if ({})      // truthy(空物件)
if ("0")     // truthy(非空字串)
if ("false") // truthy

const 鎖「重新指派」,不鎖內容

const arr = [1,2,3];
arr.push(4);    // ✅ 合法,改內容 OK
arr = [5,6];    // ❌ 報錯,重新指派不行

型別轉換:+ 與 - 不一樣

1 + "2"     // "12"  (+ 遇字串→相接)
"5" - 2     // 3     (- * / % →轉數字)
0 == ""     // true  (== 會隱式轉型)
0 === ""    // false (=== 型別也要相同)
面試/實務都用 ===,避免隱式轉型的坑。

var / let / const 與 TDZ

// var:函式作用域,提升並自動給 undefined
// let/const:區塊作用域,提升但不初始化 → TDZ
console.log(x); let x;   // ❌ 報錯(宣告前用)
let y; console.log(y);   // ✅ undefined(宣告後用)
判斷法:先看「使用點在宣告的上面還是下面」,再看 var 還是 let/const。

箭頭函式的 this

箭頭 ()=>{} 沒有自己的 this,用「定義時外層的 this」(語彙作用域);普通 function(){} 的 this 看「誰呼叫它」。callback 用箭頭才不會搞丟 this。

undefined vs null

undefined=宣告了沒賦值(系統給的);null=主動設成空(自己給的);完全沒宣告就用=ReferenceError
// 用就熟,不是背。忘了就開來查。 — 6/25