為了提高程序性能,本類型內部定義了一個myBufferedInfos的哈希列表,該列表保存了各種應用程序類型和數據庫的映射關系,在GetBindInfo函數中,程序首先檢查myBufferedInfos列表獲得緩存的數據。若緩存中沒有所需的數據,則使用Attribute.GetCustomAttribute函數從指定的對象類型中獲得附加的BindTableAttribute特性,若沒有獲得特性則表示對象類型沒有附加特性,因此無法獲得任何綁定信息。若獲得了一個BindTableAttribute對象,則創建一個TableBindInfo對象,填充TableBindInfo中的信息。
接著程序調用對象類型的GetProperties函數獲得該對象類型中定義的所有屬性,這裡使用了一種System.Reflection.BindingFlags類型的參數,該參數就指明獲得的屬性的樣式,其中Instance樣式指明只查找實例屬性,而不是靜態屬性;Public樣式指明只查找公開的屬性(public),不查找私有的屬性。GetProperties函數返回的是一個System.Reflection.PropertyInfo類型的數組,然後我們遍歷所有找到的屬性,對每一個屬性調用Attribute.GetCustomAttribute函數獲得該屬性附件的類型為BindFieldAttribute特性,若找到則表示該對象屬性映射到數據庫字段中,於是創建一個FieldBindInfo類型的對象,填充該對象。完成對所有的屬性的遍歷後,我們就設置TableBindInfo的FIElds字段,然後將獲得的TableBindInfo對象保存在myBufferedInfos中,最後函數返回創建的TableBindInfo對象,這個就是指定應用對象類型的數據庫映射信息。
在ORM框架操作數據庫時會頻繁的調用GetBindInfo函數獲得對象類型的數據庫映射關系,因此需要使用myBufferedInfos哈希列表緩存這種映射關系,這會比較大的提高框架程序的運行性能。
查詢數據
框架定義了一個ReadObjects的函數用於查詢數據庫獲得數據,並根據對象-數據庫映射關系創建若干個應用程序對象。其主要代碼為
/// <summary>
/// 使用指定的SQL查詢語句查詢數據庫並讀取多條數據庫記錄對象
/// </summary>
/// <param name="strSQL">SQL查詢語句</param>
/// <param name="ObjectType">要讀取的對象類型</param>
/// <param name="MaxObjectCount">最多讀取的對象個數</param>
/// <returns>讀取的對象組成的數組</returns>
public object[] ReadObjects( string strSQL , Type ObjectType , int MaxObjectCount )
{
// 檢查參數
if( strSQL == null )
{
throw new ArgumentNullException("strSQL");
}
if( ObjectType == null )
{
throw new ArgumentNullException("ObjectType");
}
// 檢查數據庫映射信息
this.CheckBindInfo( ObjectType , false );
// 檢查數據庫連接
this.CheckConnetion();
// 創建SQL命令對象
using( System.Data.IDbCommand cmd = myConnection.CreateCommand())
{
// 執行SQL查詢,獲得一個數據讀取器
cmd.CommandText = strSQL ;
System.Data.IDataReader reader = cmd.ExecuteReader(
MaxObjectCount == 1 ?
System.Data.CommandBehavior.SingleRow :
System.Data.CommandBehavior.SingleResult );
System.Collections.ArrayList list = new System.Collections.ArrayList();
TableBindInfo table = this.GetBindInfo( ObjectType );
lock( table )
{
// 設置字段序號,提高性能
foreach( FieldBindInfo field in table.FIElds )
{
field.FIEldIndex = - 1 ;
}
for( int iCount = 0 ; iCount < reader.FIEldCount ; iCount ++ )
{
string name = reader.GetName( iCount );
foreach( FieldBindInfo field in table.FIElds )
{
if( EqualsFieldName( name , field.FIEldName ))
{
field.FIEldIndex = iCount ;
}
}
}
while( reader.Read())
{
// 根據對象類型創建對象實例
object obj = System.Activator.CreateInstance( ObjectType );
// 讀取對象屬性值
if( InnerReadValues( obj , table , reader ) > 0 )
{
list.Add( obj );
}
if( MaxObjectCount > 0 || list.Count == MaxObjectCount )
{
break;
}
}//while
}//lock
reader.Close();
// 返回讀取的對象數組
return list.ToArray();
}//using
}
/// <summary>
/// 從數據讀取器中讀取數據並填充到一個對象中
/// </summary>
/// <param name="ObjInstance">對象實例</param>
/// <param name="info">數據庫綁定信息對象</param>
/// <param name="reader">數據讀取器</param>
private int InnerReadValues( object ObjInstance , TableBindInfo info , System.Data.IDataReader reader )
{
// 檢查參數
if( ObjInstance == null )
{
throw new ArgumentNullException("ObjectInstance");
}
if( info == null )
{
throw new ArgumentNullException("info");
}
if( reader == null )
{
throw new ArgumentNullException("reader");
}
int FIEldCount = 0 ;
// 依次讀取各個屬性值
foreach( FieldBindInfo field in info.FIElds )
{
// 綁定的屬性是只讀的
if( fIEld.Property.CanWrite == false )
{
continue ;
}
// 沒有找到綁定的字段
if( field.FIEldIndex < 0 )
{
continue ;
}
// 讀取數據字段值
object v = reader.GetValue( field.FIEldIndex );
v = fIEld.FromDataBase( v );
// 設置對象屬性值
fIEld.Property.SetValue( ObjInstance , v , null );
FIEldCount ++ ;
}//foreach
return FIEldCount ;
}
該函數的參數為SQL查詢語句,要創建的對象類型和最多能創建的對象的個數。在該函數中,首先根據數據庫連接對象創建一個命令對象,然後執行SQL查詢語句,獲得一個System.Data.IDataReader對象,然後調用GetBindInfo函數獲得對象類型和數據庫的映射信息。首先對數據讀取器的各個字段名稱和對象類型中綁定的各個屬性的名稱進行比較,設置各個對象類型的屬性對應的字段序號,以加快數據讀取速度。
然後遍歷數據讀取器,對每行記錄使用System.Activator.CreateInstance創建指定類型的對象實例,然後調用InnerReadValue函數從數據讀取器中讀取數據並填充對象的屬性值。