比较DataTable和实体类

以前喜欢DataTable,觉得它通用性强,只要一条SQL语句就可以自动映射出所有的列;相比之下,实体类必须提前创建好,映射的时候又太死,还绕了个圈不直接。

现在能力提高了,终于发现了实体类的优势,那是DataTable远远不能相比的,只不过目前有一个自己写的项目还没完成,是基于DataTable的,还不能立刻使用实体类,真的可惜。

特别说明:我要说的实体类,绝对不是EF等现有的ORM框架,我根本没看过那些框架,我仅从自己的经验得出实体类的强势,并加以改良,我敢说,现有的著名框架都没达到我这个程度。

 

先说说DataTable的局限性,它的灵活性带来的一个最大的问题就是:开发通用模块不方便。在数据库编程中,通用模块往往需要强类型的传递,弱类型如果因为内部列有变化,会导致调用模块出错,达不到预期效果。

再说说实体类的强势,传统的实体类是强类型的,但是有一种动态实体类的概念,让实体类支持弱类型,这样实体类就把DataTable所能处理的功能都包含了,剩下的事就是设计者怎么设计这个动态实体类和强名实体类的结合使用了,现有ORM框架都不支持动态实体类,这也是我断言我设计思路的先进性。

 

下面简单说下动态实体类的技术点,灵感来自Dapper(仅限.NET4.0以上版本,低版本需要改造)

这个是Dapper中定义的一个动态类型,也可以使用微软提供的ExpandoObject类,效果类似:

ExpandedBlockStart.gif 动态类
         private  class FastExpando : System.Dynamic.DynamicObject, IDictionary< stringobject>
        {
            IDictionary< stringobject> data;

             public  static FastExpando Attach(IDictionary< stringobject> data)
            {
                 return  new FastExpando { data = data };
            }

             public  override  bool TrySetMember(System.Dynamic.SetMemberBinder binder,  object value)
            {
                data[binder.Name] = value;
                 return  true;
            }

             public  override  bool TryGetMember(System.Dynamic.GetMemberBinder binder,  out  object result)
            {
                 return data.TryGetValue(binder.Name,  out result);
            }

             public  override IEnumerable< string> GetDynamicMemberNames()
            {
                 return data.Keys;
            }

             #region IDictionary<string,object> Members

             void IDictionary< stringobject>.Add( string key,  object value)
            {
                 throw  new NotImplementedException();
            }

             bool IDictionary< stringobject>.ContainsKey( string key)
            {
                 return data.ContainsKey(key);
            }

            ICollection< string> IDictionary< stringobject>.Keys
            {
                 get {  return data.Keys; }
            }

             bool IDictionary< stringobject>.Remove( string key)
            {
                 throw  new NotImplementedException();
            }

             bool IDictionary< stringobject>.TryGetValue( string key,  out  object value)
            {
                 return data.TryGetValue(key,  out value);
            }

            ICollection< object> IDictionary< stringobject>.Values
            {
                 get {  return data.Values; }
            }

             object IDictionary< stringobject>. this[ string key]
            {
                 get
                {
                     return data[key];
                }
                 set
                {
                     if (!data.ContainsKey(key))
                    {
                         throw  new NotImplementedException();
                    }
                    data[key] = value;
                }
            }

             #endregion

             #region ICollection<KeyValuePair<string,object>> Members

             void ICollection<KeyValuePair< stringobject>>.Add(KeyValuePair< stringobject> item)
            {
                 throw  new NotImplementedException();
            }

             void ICollection<KeyValuePair< stringobject>>.Clear()
            {
                 throw  new NotImplementedException();
            }

             bool ICollection<KeyValuePair< stringobject>>.Contains(KeyValuePair< stringobject> item)
            {
                 return data.Contains(item);
            }

             void ICollection<KeyValuePair< stringobject>>.CopyTo(KeyValuePair< stringobject>[] array,  int arrayIndex)
            {
                data.CopyTo(array, arrayIndex);
            }

             int ICollection<KeyValuePair< stringobject>>.Count
            {
                 get {  return data.Count; }
            }

             bool ICollection<KeyValuePair< stringobject>>.IsReadOnly
            {
                 get {  return  true; }
            }

             bool ICollection<KeyValuePair< stringobject>>.Remove(KeyValuePair< stringobject> item)
            {
                 throw  new NotImplementedException();
            }

             #endregion

             #region IEnumerable<KeyValuePair<string,object>> Members

            IEnumerator<KeyValuePair< stringobject>> IEnumerable<KeyValuePair< stringobject>>.GetEnumerator()
            {
                 return data.GetEnumerator();
            }

             #endregion

             #region IEnumerable Members

            IEnumerator IEnumerable.GetEnumerator()
            {
                 return data.GetEnumerator();
            }

             #endregion
        }

这个动态类在.NET4.0里面已经可以很好的工作了,用它动态加载数据,就是一个动态实体类。但是有一个缺陷,就是无法从表格控件中加载这些数据,类似GridView的控件,是通过反射来获取类属性的,但是动态类不支持反射内部属性,因此Dapper只完成了一半工作,剩下的一半工作就需要自己来完成了。

给动态类添加反射支持:

ExpandedBlockStart.gif 自定义属性描述类
         class FastExpandoDescriptionProvider : TypeDescriptionProvider
        {
             public FastExpandoDescriptionProvider() :  base() { }

             public  override ICustomTypeDescriptor GetTypeDescriptor(Type objectType,  object instance)
            {
                 return  new FastExpandoCustomTypeDescriptor(objectType, instance);
            }
        }

         class FastExpandoCustomTypeDescriptor : CustomTypeDescriptor
        {
             public FastExpandoCustomTypeDescriptor(Type objectType,  object instance)
                :  base()
            {
                 if (instance !=  null)
                {
                     var tmp = (FastExpando)instance;
                     var names = tmp.GetDynamicMemberNames();
                     foreach ( var name  in names)
                    {
                        customFields.Add( new DynamicPropertyDescriptor(name, instance));
                    }
                }
            }
            List<PropertyDescriptor> customFields =  new List<PropertyDescriptor>();
             public  override PropertyDescriptorCollection GetProperties()
            {
                 return  new PropertyDescriptorCollection(customFields.ToArray());
            }

             public  override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
            {
                 return  new PropertyDescriptorCollection(customFields.ToArray());
            }
        }
         class DynamicPropertyDescriptor : PropertyDescriptor
        {
            Type propertyType =  typeof( object);
             public DynamicPropertyDescriptor( string name,  object instance)
                :  base(name,  null)
            {
                 var obj = (IDictionary< stringobject>)instance;
                propertyType = obj[name].GetType();
            }

             public  override  bool CanResetValue( object component)
            {
                 return  false;
            }

             public  override Type ComponentType
            {
                 get
                {
                     return  typeof(FastExpando);
                }
            }

             public  override  object GetValue( object component)
            {
                IDictionary< stringobject> obj = (IDictionary< stringobject>)component;
                 return obj[Name];
            }

             public  override  bool IsReadOnly
            {
                 get
                {
                     return  false;
                }
            }

             public  override Type PropertyType
            {
                 get
                {
                     return propertyType;
                }
            }

             public  override  void ResetValue( object component)
            {
                 throw  new NotImplementedException();
            }

             public  override  void SetValue( object component,  object value)
            {
                IDictionary< stringobject> obj = (IDictionary< stringobject>)component;
                obj[Name] = value;
            }

             public  override  bool ShouldSerializeValue( object component)
            {
                 return  false;
            }
        }

接下来只要在任何地方(建议在静态构造函数中)添加如下代码,这个动态类就可以成功给界面视图控件加载了:

FastExpandoDescriptionProvider provider =  new FastExpandoDescriptionProvider();
TypeDescriptor.AddProvider(provider,  typeof(FastExpando));

 

这样结合强名实体类,就再有没有使用DataTable的必要了。由于我目前还没办法完全扔掉DataTable,这个实体类的设计暂时搁下,构思已经全部好了,最终实现的实体类操作,高效且强大,前景诱人。

 

转载于:https://www.cnblogs.com/qldsrx/archive/2012/03/09/2387290.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值