GetBindInfo 快取機制
- 內部
Hashtable myBufferedInfos 快取型別 → TableBindInfo 映射關係。
- 優先檢查快取,未命中才用
Attribute.GetCustomAttribute 讀取 BindTableAttribute、BindFieldAttribute。
- 建立
TableBindInfo、FieldBindInfo[] 填充欄位序號、屬性資訊、格式化設定,存入快取並回傳。
- 頻繁呼叫時快取大幅提升效能。
ReadObjects 查詢資料核心流程
public object[] ReadObjects(string sql, Type objType, int maxCount)
{
// 參數檢查、映射資訊檢查、連線檢查
using (IDbCommand cmd = conn.CreateCommand())
{
cmd.CommandText = sql;
IDataReader reader = cmd.ExecuteReader(maxCount == 1 ? CommandBehavior.SingleRow : CommandBehavior.SingleResult);
ArrayList list = new ArrayList();
TableBindInfo table = GetBindInfo(objType);
lock (table)
{
// 建立欄位索引映射 (reader 欄位序號 → FieldBindInfo)
foreach (FieldBindInfo f in table.Fields) f.FieldIndex = -1;
for (int i = 0; i < reader.FieldCount; i++)
{
string name = reader.GetName(i);
foreach (FieldBindInfo f in table.Fields)
if (EqualsFieldName(name, f.FieldName)) f.FieldIndex = i;
}
while (reader.Read())
{
object obj = Activator.CreateInstance(objType);
if (InnerReadValues(obj, table, reader) > 0) list.Add(obj);
if (maxCount > 0 && list.Count == maxCount) break;
}
}
reader.Close();
return list.ToArray();
}
}
InnerReadValues 填充物件屬性
private int InnerReadValues(object obj, TableBindInfo info, IDataReader reader)
{
int count = 0;
foreach (FieldBindInfo f in info.Fields)
{
if (!f.Property.CanWrite) continue;
if (f.FieldIndex < 0) continue;
object val = reader.GetValue(f.FieldIndex);
val = f.FromDataBase(val); // 格式化/型別轉換
f.Property.SetValue(obj, val, null);
count++;
}
return count;
}
設計重點
- 鎖定
TableBindInfo 確保多執行緒下快取建立與欄位索引映射執行緒安全。
- 預先建立
FieldIndex 避免每列重複字串比對,提升讀取效能。
Activator.CreateInstance 動態建立實體實例。
FieldBindInfo.FromDataBase 統一處理 DBNull、格式化解析、型別轉換。