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

Castle ActiveRecord 實戰(10):Schema 生成陷阱深度解析與避坑指南

     編輯:關於.NET

前言:一個關於資料遺失的真實案例

在使用 ActiveRecord 自動建立資料表時,許多開發者認為「表已存在則不會有任何動作」。但實際測試發現:若直接呼叫 ActiveRecordStarter.CreateSchema(),已存在的資料表會被 Drop 重建,導致資料全部遺失。本文深入原始碼分析這一行為差異,釐清各 Schema 方法的真實語意。

核心方法對照表

方法用途底層實現資料安全性
CreateSchema()依實體類別建立資料表NHibernate SchemaExport.Create(false, true)⚠️ 會刪除現有表並重建
DropSchema()刪除資料表NHibernate SchemaExport.Create(true, false)❌ 僅刪除表結構
CreateSchemaFromFile()執行外部 SQL 腳本建表ActiveRecord 自有 ARSchemaCreator✅ 表存在則忽略錯誤,資料安全
GenerateCreationScripts()產生建表 SQL 腳本檔NHibernate SchemaExport✅ 僅產生檔案,不執行
GenerateDropScripts()產生刪表 SQL 腳本檔NHibernate SchemaExport✅ 僅產生檔案,不執行

深度剖析:為什麼 CreateSchema() 會刪資料?

追蹤原始碼:

// ActiveRecordStarter.CreateSchema()
public static void CreateSchema() {
    foreach (var config in ActiveRecordBase._holder.GetAllConfigurations()) {
        var export = CreateSchemaExport(config);
        export.Create(false, true); // script=false, export=true
    }
}

// NHibernate SchemaExport.Create()
public void Create(bool script, bool export) {
    Execute(script, export, false, true); // justDrop=false, format=true
}

// NHibernate SchemaExport.Execute() 關鍵邏輯
public void Execute(bool script, bool export, bool justDrop, bool format) {
    // 1. 總是先執行 DROP 腳本
    // 2. 若 justDrop=false,再執行 CREATE 腳本
    // 3. 相當於執行:
    // IF EXISTS (SELECT * FROM sysobjects WHERE ...) DROP TABLE Blogs
    // CREATE TABLE Blogs (...)
}

結論:CreateSchema() 內部會無條件先執行 DROP TABLE IF EXISTS,再 CREATE TABLE。這在開發環境重建結構方便,但在正式環境極度危險!

安全建表策略:CreateSchemaFromFile()

此方法透過 ARSchemaCreator.ExecuteScriptParts() 逐條執行 SQL,catch 區塊直接吞掉例外並輸出 Debug 訊息:

try {
    statement.CommandText = part;
    statement.ExecuteNonQuery();
} catch (Exception ex) {
    Debug.WriteLine($"SQL: {part} threw {ex.Message}. Ignoring");
}

因此:若資料表已存在,執行 CREATE TABLE 會拋出例外,被忽略,現有表結構與資料完好無損。這才是「表不存在才建立」的正確語意。

最佳實踐建議

  1. 開發期:使用 CreateSchema() 快速重建結構,配合測試資料重灌。
  2. 部署/產線:嚴禁直接呼叫 CreateSchema()。改用:
    • 方案 A:預先產生 SQL 腳本(GenerateCreationScripts()),由 DBA 審核後手動執行。
    • 方案 B:使用 CreateSchemaFromFile() 執行版本控管的遷移腳本(需自行處理 IF NOT EXISTS 邏輯)。
  3. 版本升級:採用資料庫遷移工具(如 FluentMigrator、DbUp)管理結構變更,勿依賴 ORM 自動建表。

總結

ActiveRecord 的 Schema 方法語意各異,CreateSchema() 實為「Drop & Recreate」,CreateSchemaFromFile() 才是「安全建表」。生產環境務必採用腳本管控方式,避免不可逆的資料災難。

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