public int InsertObjects(IEnumerable objects, string tableName)
{
if (objects == null) throw new ArgumentNullException("objects");
CheckBindInfo(objects, false); // 不強制 Key
ArrayList list = new ArrayList(); foreach (object o in objects) list.Add(o);
if (list.Count == 0) return 0;
CheckConnection();
string lastSql = null; int insertCount = 0;
using (IDbCommand cmd = conn.CreateCommand())
{
foreach (object obj in list)
{
TableBindInfo table = GetBindInfo(obj.GetType());
string targetTable = string.IsNullOrEmpty(tableName) ? table.TableName : tableName;
ArrayList values = new ArrayList();
StringBuilder cols = new StringBuilder(), vals = new StringBuilder();
foreach (FieldBindInfo f in table.Fields)
{
if (!f.Property.CanRead) throw new Exception($"屬性 {f.Property.Name} 不可讀");
object val = f.Property.GetValue(obj, null);
if (val == null || DBNull.Value.Equals(val)) continue; // 跳過 Null
if (cols.Length > 0) { cols.Append(", "); vals.Append(", "); }
cols.Append(FixFieldName(f.FieldName));
vals.Append("?");
values.Add(f.ToDataBase(val));
}
if (cols.Length == 0) continue;
string sql = $"INSERT INTO {FixTableName(targetTable)} ({cols}) VALUES ({vals})";
// SQL 快取優化:相同 SQL 結構重用命令物件參數集合
if (sql != lastSql)
{
lastSql = sql;
cmd.Parameters.Clear();
cmd.CommandText = sql;
for (int i = 0; i < values.Count; i++) cmd.Parameters.Add(cmd.CreateParameter());
}
// 填充參數值
for (int i = 0; i < values.Count; i++)
((IDbDataParameter)cmd.Parameters[i]).Value = values[i];
insertCount += cmd.ExecuteNonQuery();
}
}
return insertCount;
}
CommandText 與參數集合結構,僅更新參數值,避免重複 Parameters.Clear/Add 開銷。? 佔位符傳遞,防止注入、型別安全。Property.CanRead 確保屬性可讀取。基於 InsertObjects 衍生單一物件插入、指定表名插入等多載,豐富框架程式介面。