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

快速 ORM 框架動態編譯:實體屬性驗證與插入命令生成邏輯 (第 12 講上第 10 部分)

     編輯:關於C語言

GetBindProperties 驗證實體類別規範

快速 ORM 要求實體類別必須:

  • 為 class、public、非 abstract。
  • 擁有公用無參數建構函式 (new T() 有效)。
  • 屬性為 public instance、型別為 CLR 基礎型別/string/DateTime。
  • 屬性標記 BindFieldAttribute 才納入映射。

private PropertyInfo[] GetBindProperties(Type recordType)
{
    if (recordType == null) throw new ArgumentNullException("recordType");
    if (!recordType.IsPublic) throw new ArgumentException($"{recordType.FullName} 非公開類型");
    if (!recordType.IsClass) throw new ArgumentException($"{recordType.FullName} 非類別");
    if (recordType.IsAbstract) throw new ArgumentException($"{recordType.FullName} 不得為抽象類別");
    if (recordType.GetConstructor(Type.EmptyTypes) == null)
        throw new ArgumentException($"{recordType.FullName} 無預設建構函式");

    var list = new ArrayList();
    foreach (PropertyInfo p in recordType.GetProperties(BindingFlags.Instance | BindingFlags.Public))
    {
        var attr = (BindFieldAttribute)Attribute.GetCustomAttribute(p, typeof(BindFieldAttribute));
        if (attr != null)
        {
            if (p.GetIndexParameters().Length > 0)
                throw new ArgumentException($"屬性 {recordType.FullName}.{p.Name} 不得為索引子");
            Type pt = p.PropertyType;
            if (!(pt.IsPrimitive || pt == typeof(string) || pt == typeof(DateTime)))
                throw new ArgumentException($"不支援屬性 {p.Name} 的型別 {pt.FullName}");
            list.Add(p);
        }
    }
    if (list.Count == 0) throw new ArgumentException($"{recordType.FullName} 無標記欄位");
    return (PropertyInfo[])list.ToArray(typeof(PropertyInfo));
}

GetBindFieldName 取得欄位名


private string GetBindFieldName(PropertyInfo p)
{
    var attr = (BindFieldAttribute)Attribute.GetCustomAttribute(p, typeof(BindFieldAttribute));
    string name = attr.Name?.Trim();
    return string.IsNullOrEmpty(name) ? p.Name : name;
}

動態生成 FillInsertCommand (DB_Employees 範例)


public override int FillInsertCommand(IDbCommand cmd, object record)
{
    // 參數檢查、型別轉換
    var emp = (DB_Employees)record;
    var fields = new ArrayList(); var values = new ArrayList();

    fields.Add("EmployeeID"); values.Add(emp.EmployeeID);
    if (emp.LastName != null) { fields.Add("LastName"); values.Add(emp.LastName); }
    fields.Add("BirthDate"); values.Add(emp.BirthDate.ToString("yyyy-MM-dd"));
    // ... 其他屬性
    fields.Add("Sex"); values.Add(emp.Sex);

    if (fields.Count == 0) return 0;
    cmd.Parameters.Clear();
    var sql = new StringBuilder();
    sql.Append("INSERT INTO Employees (").Append(ConcatStrings(fields)).Append(") VALUES (");
    for (int i = 0; i < values.Count; i++)
    {
        if (i > 0) sql.Append(", ");
        sql.Append(cmd.CreateParameter().ParameterName); // @p0 或 ?
        var p = cmd.CreateParameter(); p.Value = values[i]; cmd.Parameters.Add(p);
    }
    sql.Append(")");
    cmd.CommandText = sql.ToString();
    return values.Count;
}

關鍵差異

  • 基礎類別 RecordORMHelper 定義虛擬方法 FillInsertCommand,動態編譯產生具體實體類別的覆寫實作。
  • 運行期產生程式碼 → 編譯 → 快存組件,後續直接呼叫強型別方法,避免反射開銷。
  • ConcatStrings 輔助方法快速連接欄位名稱。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved