我正在寻找为生产服务器创建数据库行到对象映射器。
我的目标是在一个位置填写数据库列名是什么,以及在该对象的哪个字段中存储从数据库查询返回的单行。
我计划稍后添加功能以自动获取表名和连接字符串。这样做的目的是集中所有与数据库相关的东西(列的命名和查询字符串自动跟随,对返回的结果添加保护,错误记录等)
我读了很多关于泛型集访问器的文章,认为我目前无法从中综合解决方案。
这是我想要实现的(非工作)骨架。欢迎所有关于优化和更好实践的评论。
用途:
/* 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
}
}
如何实现由 ReadObject() 填充的指定字段(Uid、Type、IpAddr 等)?我需要一个等效于指向成员的指针......我也读过反射,但我不确定效率并且不理解 100% 如何实现它。
注意:我宁愿不使用完整的 ORM 解决方案——我的理解是它不是一个战略性的长期解决方案(对于未来的实现、支持等不太灵活——更容易但不是真正的企业级)。我想保持对数据库映射层的控制,同时减少生产服务器未来开发中出现的故障。
你们如何看待这个实施,实现我的目标的最佳方式是什么?
感谢您的宝贵时间,并致以最诚挚的问候,
墨菲斯