実稼働サーバー用のデータベースの行からオブジェクトへのマッパーを作成しようとしています。
私の目標は、データベースの列名を 1 つの場所に入力し、データベース クエリから返された 1 つの行をこのオブジェクトのどのフィールドに格納するかを指定することです。
後でテーブル名と接続文字列を自動的に取得する機能を追加する予定です。これを行う目的は、すべてのデータベース関連のものを一元化することです (列の名前付けとクエリ文字列が自動的に続き、返された結果に保護を追加し、エラー ログなど)。
現在、そこからソリューションを合成できないと考えているジェネリック セット アクセサーについてよく読んでいます。
これは、私が達成しようとしているものの(動作していない)スケルトンです。最適化とより良い実践についても、すべてのコメントを歓迎します。
利用 :
/* get MediaInfo filled regarding CDbColumnFind criterias */
CEventReportingMediaInfo MediaInfo = DbQuery(1, new CDbColumnFind() { Name = "uid", Value = "2" });
これがDb-Mappable基本クラスです
public class DbMappableClass
{
/********************************************/
/* required fields for database information */
/********************************************/
public string TableName;
public IList TableColumns;
/********************************************/
/* generic object filling helper */
/********************************************/
public void ReadObject(DataRow FromRow)
{
foreach (CDbColumn Column in TableColumns)
{
TryParseGeneric(FromRow[Column.Name].ToString(), Column.Field);
}
}
/********************************************/
/* conversion helper */
/********************************************/
public static bool TryParseGeneric(string src, T value)
{
TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
try
{
value = (T)converter.ConvertFromString(src);
return true;
}
catch
{
value = default(T);
CSysLog.WriteEntry(SysLogLevel.WARNING, "failed to convert src ({0}) to type ({1}), use default value ({2})", src.ToString(), typeof(T), value);
return false;
}
}
/********************************************/
/* Db column type */
/********************************************/
public class CDbColumn
{
private readonly string name;
private readonly SqlDbType sqltype;
private readonly Type ctype;
public CDbColumn(string Name, SqlDbType SqlType, object Field)
{
this.name = Name;
this.sqltype = SqlType;
this.Field = Field;
this.ctype = Field.GetType();
}
public string Name { get { return name; } }
public SqlDbType SqlType { get { return sqltype; } }
public object Field { get; set; }
public Type CType { get { return ctype; } }
}
/********************************************/
/* Db Query type criterias */
/********************************************/
public class CDbColumnFind
{
public string Name;
public object Value;
}
/********************************************/
/* Generic Db Query */
/********************************************/
public static TReturnType DbQuery(int ExpectedCount, params CDbColumnFind[] Args) where TReturnType : DbMappableClass, new()
{
/* query database, obtain results in RowResults ... */
TReturnType ReturnResult = new TReturnType();
DataRow RowResults = TableResult.Rows[0];
ReturnResult.ReadObject(RowResults);
}
}
db-mappable 派生オブジェクトのカスタムで一元化された宣言になりました
/********************************************/
/* Event Reporting Media Table : Database */
/********************************************/
public class CEventReportingMediaInfo : DbMappableClass
{
/**********************************/
/** Member Declaration ***/
/**********************************/
public int Uid { get; set; }
public MediaType Type { get; set; }
public string IpAddr { get; set; }
public Int32 Port { get; set; }
public MediaStatus Status { get; set; }
public int Delay { get; set; }
/**********************************/
/** Database Informations ***/
/**********************************/
public CEventReportingMediaInfo()
{
TableName = "event_reporting_media_tbl";
TableColumns = new ReadOnlyCollection (new[] {
new CDbColumn ("uid" , SqlDbType.Int, Uid),
new CDbColumn ("media_type" , SqlDbType.TinyInt, Type),
new CDbColumn ("media_ip" , SqlDbType.VarChar, IpAddr),
new CDbColumn ("media_port" , SqlDbType.Int, Port),
new CDbColumn ("media_status" , SqlDbType.TinyInt, Status),
new CDbColumn ("media_delay" , SqlDbType.Int, Delay)
});
}
public enum MediaType
{
INVALID = 0,
SIP_GATEWAY = 1,
MODEM = 2
}
public enum MediaStatus
{
OFFLINE = 0,
ONLINE = 1
}
}
特定のフィールド (Uid、Type、IpAddr など) を一般的に ReadObject() で埋めるにはどうすればよいですか? メンバーへのポインターに相当するものが必要です...リフレクションについても読みましたが、効率についてはよくわからず、実装方法を100%理解していません。
注: 完全な ORM ソリューションを使用しないことをお勧めします。私の理解では、それは戦略的な長期的なソリューションではありません (将来の実装、サポートなどの柔軟性が低くなります。より簡単ですが、実際にはエンタープライズ グレードではありません)。本番サーバーでの将来の開発でグリッチの発生を減らしながら、db マッピング レイヤーの制御を維持したいと考えています。
この実装についてどう思いますか?私の目標を達成するための最良の方法は何ですか?
お時間をいただきありがとうございます。よろしくお願いいたします。
モーフィアス