比較DataTable和實體類

來源:互聯網
上載者:User

以前喜歡DataTable,覺得它通用性強,只要一條SQL語句就可以自動對應出所有的列;相比之下,實體類必須提前建立好,映射的時候又太死,還繞了個圈不直接。

現在能力提高了,終於發現了實體類的優勢,那是DataTable遠遠不能相比的,只不過目前有一個自己寫的項目還沒完成,是基於DataTable的,還不能立刻使用實體類,真的可惜。

特別說明:我要說的實體類,絕對不是EF等現有的ORM架構,我根本沒看過那些架構,我僅從自己的經驗得出實體類的強勢,並加以改良,我敢說,現有的著名架構都沒達到我這個程度。

 

先說說DataTable的局限性,它的靈活性帶來的一個最大的問題就是:開發通用模組不方便。在資料庫編程中,通用模組往往需要強型別的傳遞,弱類型如果因為內部列有變化,會導致調用模組出錯,達不到預期效果。

再說說實體類的強勢,傳統的實體類是強型別的,但是有一種動態實體類的概念,讓實體類支援弱類型,這樣實體類就把DataTable所能處理的功能都包含了,剩下的事就是設計者怎麼設計這個動態實體類和強名實體類的結合使用了,現有ORM架構都不支援動態實體類,這也是我斷言我設計思路的先進性。

 

下面簡單說下動態實體類的技術點,靈感來自Dapper(僅限.NET4.0以上版本,低版本需要改造)

這個是Dapper中定義的一個動態類型,也可以使用微軟提供的ExpandoObject類,效果類似:

動態類        private class FastExpando : System.Dynamic.DynamicObject, IDictionary<string, object>
        {
            IDictionary<string, object> data;

            public static FastExpando Attach(IDictionary<string, object> 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<string, object>.Add(string key, object value)
            {
                throw new NotImplementedException();
            }

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

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

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

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

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

            object IDictionary<string, object>.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<string, object>>.Add(KeyValuePair<string, object> item)
            {
                throw new NotImplementedException();
            }

            void ICollection<KeyValuePair<string, object>>.Clear()
            {
                throw new NotImplementedException();
            }

            bool ICollection<KeyValuePair<string, object>>.Contains(KeyValuePair<string, object> item)
            {
                return data.Contains(item);
            }

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

            int ICollection<KeyValuePair<string, object>>.Count
            {
                get { return data.Count; }
            }

            bool ICollection<KeyValuePair<string, object>>.IsReadOnly
            {
                get { return true; }
            }

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

            #endregion

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

            IEnumerator<KeyValuePair<string, object>> IEnumerable<KeyValuePair<string, object>>.GetEnumerator()
            {
                return data.GetEnumerator();
            }

            #endregion

            #region IEnumerable Members

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

            #endregion
        }

這個動態類在.NET4.0裡面已經可以很好的工作了,用它動態載入資料,就是一個動態實體類。但是有一個缺陷,就是無法從表格控制項中載入這些資料,類似GridView的控制項,是通過反射來擷取類屬性的,但是動態類不支援反射內部屬性,因此Dapper只完成了一半工作,剩下的一半工作就需要自己來完成了。

給動態類添加反射支援:

自訂屬性描述類        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<string, object>)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<string, object> obj = (IDictionary<string, object>)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<string, object> obj = (IDictionary<string, object>)component;
                obj[Name] = value;
            }

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

接下來只要在任何地方(建議在靜態建構函式中)添加如下代碼,這個動態類就可以成功給介面視圖控制項載入了:

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

 

這樣結合強名實體類,就再有沒有使用DataTable的必要了。由於我目前還沒辦法完全扔掉DataTable,這個實體類的設計暫時擱下,構思已經全部好了,最終實現的實體類操作,高效且強大,前景誘人。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.