首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

ASP.NET Access 環境下取得新增文章 ID 實作:預存程序 + GetAutoID 策略

     編輯:ASP.NET 基礎

業務場景:文章發布需即時取得自增 ID

在 Access 資料庫環境中,新增文章後需立即取得 ArticleID (自增欄位) 以供後續關聯操作 (如上傳圖片、建立分類關聯)。本文展示一套「預存程序 + 手動取得 Max ID + 1」的經典實作模式。

核心流程

  1. 呼叫 GetAutoID("ArticleID", "Article", connStr) 取得下一可用 ID。
  2. 將 ID 連同文章內容以參數化方式傳入預存程序 AddArticle。
  3. 執行預存程序完成插入,返回 ID 給呼叫端。

關鍵代碼實作

1. 業務邏輯層:新增文章

public int AddArticle(string title, string author, string from, int creator, int modifier,
    string content, int channelId, bool isTop, bool isCommend, bool isCheck,
    string keyword, string introduction)
{
    int articleId = -1;

    // HTML 編碼防 XSS
    title = HttpUtility.HtmlEncode(title);
    author = HttpUtility.HtmlEncode(author);
    keyword = HttpUtility.HtmlEncode(keyword);

    using (OleDbConnection conn = new OleDbConnection(Globals.ConnectString))
    using (OleDbCommand cmd = new OleDbCommand("AddArticle", conn))
    {
        cmd.CommandType = CommandType.StoredProcedure;

        // 關鍵:先取得下一個 ID
        articleId = DataProvider.GetAutoID("ArticleID", "Article", Globals.ConnectString);
        cmd.Parameters.Add("ArticleID", articleId);
        cmd.Parameters.Add("ArticleTitle", title);
        cmd.Parameters.Add("Author", author);
        cmd.Parameters.Add("ArticleFrom", from);
        cmd.Parameters.Add("Creator", creator);
        cmd.Parameters.Add("ModifyBy", modifier);
        cmd.Parameters.Add("Content", content);
        cmd.Parameters.Add("ChannelID", channelId);
        cmd.Parameters.Add("IsOnTop", isTop);
        cmd.Parameters.Add("IsCommend", isCommend);
        cmd.Parameters.Add("IsCheck", isCheck);
        cmd.Parameters.Add("Keyword", keyword);
        cmd.Parameters.Add("ArticleIntroduction", introduction);

        DataProvider.ExecNonQueryOle(cmd);
    }
    return articleId;
}

2. 資料存取層:GetAutoID 實作

public static int GetAutoID(string fieldName, string tableName, string connectString)
{
    using (OleDbConnection conn = new OleDbConnection(connectString))
    using (OleDbCommand cmd = new OleDbCommand($"Select Max({fieldName}) as MaxID from {tableName}", conn))
    {
        cmd.CommandType = CommandType.Text;
        DataSet ds = GetDataSetOle(cmd);
        if (ds.Tables[0].Rows[0][0] == DBNull.Value)
            return 1; // 資料表為空
        return int.Parse(ds.Tables[0].Rows[0][0].ToString()) + 1;
    }
}

public static DataSet GetDataSetOle(OleDbCommand cmd)
{
    using (OleDbDataAdapter adapter = new OleDbDataAdapter(cmd))
    {
        DataSet ds = new DataSet();
        if (cmd.Connection.State != ConnectionState.Open) cmd.Connection.Open();
        adapter.Fill(ds);
        return ds;
    }
}

3. 預存程序範例 (Access SQL)

CREATE PROCEDURE AddArticle
(
    ArticleID LONG,
    ArticleTitle TEXT(255),
    Author TEXT(100),
    ArticleFrom TEXT(100),
    Creator LONG,
    ModifyBy LONG,
    Content MEMO,
    ChannelID LONG,
    IsOnTop YESNO,
    IsCommend YESNO,
    IsCheck YESNO,
    Keyword TEXT(100),
    ArticleIntroduction MEMO
)
AS
INSERT INTO Article (ArticleID, ArticleTitle, Author, ArticleFrom, Creator, ModifyBy, Content, ChannelID, IsOnTop, IsCommend, IsCheck, Keyword, ArticleIntroduction)
VALUES (ArticleID, ArticleTitle, Author, ArticleFrom, Creator, ModifyBy, Content, ChannelID, IsOnTop, IsCommend, IsCheck, Keyword, ArticleIntroduction);

潛在風險與改進方向

風險說明改進建議
並發衝突多用戶同時新增,Max(ID)+1 可能重複改用 @@IDENTITY 或資料庫層面自增欄位,勿手動算 ID
SQL InjectionGetAutoID 字串拼接 Table/Field Name白名單驗證欄位/表名,或改用參數化查詢 (Access 不支援參數化識別碼)
效能每次新增需額外查詢 Max(ID)單指令 INSERT ...; SELECT @@IDENTITY 完成

現代化替代方案

// 使用 OleDb 單指令取得新增 ID (Access 支援)
cmd.CommandText = "INSERT INTO Article(...) VALUES(...); SELECT @@IDENTITY";
int newId = Convert.ToInt32(cmd.ExecuteScalar());

此做法:

  • 原子性:插入與取 ID 同一連線、同一指令完成。
  • 並發安全:資料庫引擎保證自增值唯一。
  • 簡潔:省去 GetAutoID、預存程序、雙次往返。

結語

「預存程序 + 手動取 ID」是早期 Access 開發的典型模式,理解其運作邏輯有助於維護舊系統。新專案或重構時,強烈建議採用 @@IDENTITY 或遷移至支援 SCOPE_IDENTITY()、OUTPUT INSERTED.ID 的現代資料庫 (SQL Server, PostgreSQL, SQLite),從根本上消除並發與效能隱憂。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved