CYQ.Data 数据层框架CYQ.Data 是一款由路过秋天创作的支持多数据库应用[Txt,Xml,Access,MSSQL,Oracle,SQLite,MySql]的底层数据库操作类库,使用本类库可以轻松快速开发项目(QQ群:6033006)。 |
MDataTable 原理解析 数据单元
框架原理 |
|
|
| #楼主 |
DataTable,你有多丰富: 轻轻的打开Reflector.exe,按下F3搜索,输入DataTable,双击定位,右键,Disassemble之后, 悄悄的点一下最下面的 Expand Methods,再从容的把它copy出来,我们才发现。。6000多行的代码 我们常用的DataTable一个类,才用了6000多行代码实现,跟我们以前写的,一个类写到一千多,就觉得有点过了 大巫见小巫啊! 解析: 当然了,不是说一个类代码越多,性能就一定不好。至少我们还是那么多人前拥后挤的在继续使用。 大而广,考虑详细,是因为面对的人群多。 针对目前这个数据访问层中,我们所需要的功能,并不需要那么多,我们只需要最常用的功能即可了, 即可以把表直接绑定控件,并访问数据行,数据列,数据单元和数据的数据库类型, 所以: 我们开始了自定义,在自定义中,我们并不继承和DataTable相关的东西。我们一步一步的构建属于自己的轻量级的Table类 下面开始构造自己的MDataTable系列类: 一.单元格:MDataCell 我们先来看我们常用的表现的一行数据,如下图: 描述: 图片上一览,第一行是列头,接下来全是数据行,那么单元格应该包含哪些内容?这,其实是个问题。如果我们从界面上看,一个单独的单元格,就只有Value了, 可是如果只是Value,那它又缺少了意义,因为你不知道它是属于什么列,简单说,如果没有列头,你的数据本身的意义,就变的很难理解, 除非这个值有很深的解释意义包含在里头。 说明: 因此,一个单元格还应该包括一个列头解释,于是。就会出现这么一个现实,如果一个单元格是由头和值组成的,那么每一行数据,都会包括重复的列头。 我们再仔细观察那图,实际上,只有一个列头,其余都是值...于是,在这里,就产生了一个可以思考的问题。 单元格需要由头和值组成,可是,又要保证数据再多,也只能存在一个表头,怎么将这个问题转化在设计的类中?? 怎么设计这样一个数据单元类?才不会有重复的单元表头,又能合理解释出数据与表头的关系? 经过长久的深思后。。一个关键的字出来了"ref",引用,是的,用的这就个,如果每个单元格,都包括值和单元表头,而单元表头,都引用同一个的时候,就刚好满足了需求。 于是,我们开始写出这样的类: 先构造出一个存放值的类: /// /// 只包函被填充的数据状态和值 /// public class MDataCellValue { /// /// //值是否为空 /// internal bool _IsNull; /// /// 值是否被改变了 /// internal bool _IsChange; /// /// 值是多少 /// internal object _Value; public MDataCellValue() { _IsNull = true; _IsChange = false; _Value = null; } } 接着,我们构造存放表头: 我们可以参考数据库,也可以参考DataCell中的数据结构,构造出以下的类: ///
/// 只包函数据库字段的属性 /// public class MDataCellStruct { internal bool _IsCanNull; internal bool _IsReadOnly; internal string _ColumnName; internal System.Data.SqlDbType _SqlType; internal int _MaxSize; internal string _Operator = "="; internal ParameterDirection _ParaDirection; #region 构造函数 public MDataCellStruct(string ColumnName, System.Data.SqlDbType SqlType, bool IsReadOnly, bool IsCanNull, int MaxSize, ParameterDirection paraDirection) { _ColumnName = ColumnName; _SqlType = SqlType; _IsReadOnly = IsReadOnly; _IsCanNull = IsCanNull; _MaxSize = MaxSize; _ParaDirection = paraDirection; } #endregion #region 属性 /// /// 数据字段列名称 /// public string ColumnName { get { return this._ColumnName; } } /// /// 数据类型 /// public System.Data.SqlDbType SqlType { get { return this._SqlType; } } /// /// 数据字段列是否为只读 /// public bool IsReadOnly { get { return this._IsReadOnly; } } /// /// 数据字段列长度大小 /// public int MaxSize { get { return this._MaxSize; } } /// /// 数据字段列值是否能为空 /// public bool IsCanNull { get { return this._IsCanNull; } } /// /// 存储过程时用的参数 /// public ParameterDirection ParaDirection { get { return this._ParaDirection; } set { _ParaDirection = (ParameterDirection)value; } } public string Operator { get { return _Operator; } set { _Operator = value; } } #endregion } 紧跟着,我们要开始构造单元格了,它包含了数据单元结构和值两个类,同时,为了让以后所有行的单元格里的表头都指向同一个,我们用出了"ref" Code
public class MDataCell { internal MDataCellValue _ValueContainer; private MDataCellStruct _DataStruct; 构造函数#region 构造函数 public MDataCell(ref MDataCellStruct dataStruct) { Init(ref dataStruct, null); } public MDataCell(ref MDataCellStruct dataStruct, object value) { Init(ref dataStruct, value); } #endregion 初始化#region 初始化 private void Init(ref MDataCellStruct dataStruct, object value) { _ValueContainer = new MDataCellValue(); _DataStruct = dataStruct; _ValueContainer._Value = value; } #endregion } 为了方便从数据单元里访问数据结构和值,我们通过增加属性来对外开放 Code
属性#region 属性 字段结构#region 字段结构 /**//// /// 操作符 /// public string Operator { get { return _DataStruct._Operator; } set { _DataStruct._Operator = value; } } public ParameterDirection ParaDirection { get { return _DataStruct._ParaDirection; } set { _DataStruct._ParaDirection = (ParameterDirection)value; } } public string ColumnName { get { return _DataStruct._ColumnName; } } public SqlDbType SqlType { get { return _DataStruct._SqlType; } } public int MaxSize { get { return _DataStruct._MaxSize; } } public bool IsCanNull { get { return _DataStruct._IsCanNull; } } public bool IsReadOnly { get { return _DataStruct._IsReadOnly; } } #endregion /**//// /// 字段结构 /// public MDataCellStruct DataStruct { get { return _DataStruct; } } /**//// /// 数据字段列值是否能改变 /// public bool IsChange { get { return _ValueContainer._IsChange; } set { _ValueContainer._IsChange = value; } } /**//// /// 数据字段列值是否为空 /// public bool IsNull { get { return _ValueContainer._IsNull; } } /**//// /// 数据字段列值 /// public object Value { get { return _ValueContainer._Value; } set { if (_DataStruct._IsCanNull)//数据库允许为null值 { _ValueContainer._Value = value; _ValueContainer._IsChange = true; _ValueContainer._IsNull = (value == null || value == DBNull.Value); } else if (value != null && value != DBNull.Value)//数据库不允许为null值不允许为null值 { _ValueContainer._Value = value; _ValueContainer._IsChange = true; _ValueContainer._IsNull = false; } } } #endregion 至此,我们终于构造完数据单元格,当然了,在对Value的Set属性中,以后我们会加上数据类型的比较和数据长度的验证,来增加数据的安全性 |
游客[注册][124.126.192.*]2011/2/23 3:02:25 | #1 | |
没大看明白。 |
发表评论
论坛公告
帖子搜索
最新帖子
最新评论
- 请教博主。我mysql的提示 V5.7.7.4 MySql.xxxx:check the tablename "tbl_site_info" is exist? error:ExeDataReader():Expression #1 of ORDER BY clause is not in SELECT list, references column 'information_schema.s1.ORDINAL_POSITION' which is not in SELECT list; this is incompatible with DISTINCT 配置如下: <?xml version="1.0" encoding="utf-8" ?> <configuration> <connectionStrings> <add name="Conn" connectionString="host=192.168.3.101;Port=3306;Database=xxxxx;uid=root;pwd=2017" providerName="MySql.Data.MySqlClient"/> </connectionStrings> </configuration>
- 查询语句有点问题,软件启动时查询语句可以从数据库查询出数据,软件一直运行时无论怎么修改数据库,查询出来的还是老数据,不知道是为什么
- 我语句中用到了union all而且两个查询都有查询条件,action.select总是不成功,不知道有没有什么好的解决办法,谢谢
- 大神,如果我想通过一个对象(从数据映射过来的)要插入的话,我需要遍历字段然后每个set一下吗?有没有更好的方法??
- 真心好用,想问下秋天直接拼写sql怕注入吗
- V4.5后,好多方法都改变了,求来个新的日志帮助
- 請問大神V5源碼要多少錢 我是和交流過的
- 楼主,,从数据库里查出来并绑定datagridview,但是显示的都是数据库里的英文名,怎么改??好纠结啊这个。。。。
- 我想问一下,主从表添加怎样处理
- 10年就过了!!!!