程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 與DotNet數據對象結合的自定義數據對象設計(二) 數據集合與DataTable

與DotNet數據對象結合的自定義數據對象設計(二) 數據集合與DataTable

編輯:關於.NET

在上篇Blog中介紹了如何定義一個與DataRow相結合的數據類,那麼本篇將介紹如何定義一個與 DataTable對應的數據集合。

在DotNet中提供了一個CollectionBase作為我們定義強類型的數據集合的抽象類,在DotNet1.1中要定 義一個強類型的數據集合就必須為每一種數據類定義一個對應的數據集合,在2.0中增加了泛型的功能後 ,這個問題得到了解決。又由於在目前的Ibatisnet版本中還不支持泛型的功能,所以數據集合可以選擇 從ArrayList或CollectionBase繼承下來。但是不管是ArrayList還是CollectionBase都不支持序列化,也 是他們都有沒有Serializable屬性,那麼實現的數據集合也將無法實現序列化,所以這邊選擇直接實現 IList接口,內部再實例化一個ArrayList做為數據容器。類的定義如下:

public class ObjectList : IList, ISerializable{}

還有一需要解決的問題是,數據類如何與DataTable對應起來呢?在數據類定義一個DataTable的屬性 和內部變量,做為存儲數據的容器。

1private DataTable m_dataTable = null;
2/**//// <summary>
3         /// Gets the data table form.
4        /// </summary>
5        /// <value>The data table form.</value>
6        public DataTable DataTableForm
7        {
8            get { return m_dataTable; }
9     }
10

因為前面有提到了,一個對象對應一個DataRow,當前一個對象單獨存在時,它的數據存放在數據類的 數據容器裡,而當中被加到一個集合裡時,數據行就應該存放在數據集合對應的DataTable裡了。那要怎 麼轉換呢?很簡單,只需要把數據行從原來(數據類的數據容器)的表裡面復制到ObjectList對應的 DataTable裡,然後將原來的行刪除就行了。這裡復制一行數據也是有學問的,因為一個DataRow一旦創建 了,它就只能被加入到創建它的那個DataTable裡,當它被加入到另外一個表裡就會拋出它同時只能屬於 一個表的異常,而如果是DataRow裡的數據一列一列地復制到另一個DataRow,就會對性能造成非常大的影 響。最理想的辦法就是數據不動,只改變DataRow記錄的一個狀態信息就行了。這裡的改變行狀態的辦法 就是NewRow,而數據不動的辦法就是將源Row的ItemArray屬性賦值給目的的ItemArray。經過測試,這樣 做可以減少1倍以上的時間成本(內存成本也一樣)。

具體的添加方法如下:

1private void AddObjectRowToListTable(IDataObject p_dataObject)
2        {
3            if (m_dataTable == null)
4                m_dataTable = p_dataObject.DataContainer.Clone();
5            DataRow m_newRow = m_dataTable.NewRow();
6            m_newRow.ItemArray = p_dataObject.ObjectRow.ItemArray;
7            /**//***********************************************
8            * 使用上面代 碼時間性能會比下面的高一倍
9            * for (int i = 0; i < p_dataObject.ObjectRow.ItemArray.Length; i++)
10               {
11                m_newRow[i] = p_dataObject.ObjectRow.ItemArray[i];
12                }
13            * ********************************************/
14
15            m_dataTable.Rows.Add(m_newRow);
16            p_dataObject.ObjectRow.Delete ();
17            p_dataObject.ObjectRow.Table.AcceptChanges();
18             p_dataObject.ObjectRow = m_newRow;
19        }
20

下一個就是序列化的問題了。序列化集合類好像比較麻煩,因為它本身並沒有為我提供支持序列化的 方法。而在這個數據集合裡,實現了ISerializable接口,由我們自己來定義要序列的方式。我們的關鍵 是序列化數據,所以就這裡的序列化就只需要序列ObjectList對應的DataTable就行了。實現 ISerializable接口如下:

1public void GetObjectData(SerializationInfo info, StreamingContext context)
2         {
3            if (this.Count >= 0)
4            {
5                info.AddValue("DataObjectType", m_list[0].GetType());  //當前數據類的類型
6            }
7
8            info.AddValue("DataTable", this.m_dataTable, typeof(DataTable));
9        }
10

同時增加一個反序列化的構造函數

1protected ObjectList(SerializationInfo info, StreamingContext context) : base()
2        {
3            m_dataTable = info.GetValue("DataTable", typeof(DataTable)) as DataTable;
4            Type m_dataObjectType = info.GetValue("DataObjectType", typeof(Type)) as Type;
5            if (m_dataObjectType != null)
6            {              
7                 foreach (DataRow m_dr in m_dataTable.Rows)
8                 {
9                    m_list.Add (Activator.CreateInstance(m_dataObjectType, m_dr));
10                }
11            }
12       }
13

這樣就可以支持序列化與反序列化了。

整個數據類的定義如下:

1[Serializable]
2    public class ObjectList1 : IList, ISerializable
3     {
4        private ArrayList m_list = null;
5        private DataTable m_dataTable = null;
6        /**//// <summary>
7        /// Initializes a new instance of the <see cref="T:ObjectList"/> class.
8         /// </summary>
9        public ObjectList1()
10        {
11            m_list = new ArrayList();
12        }
13         /**//// <summary>
14        /// Gets the data table form.
15         /// </summary>
16        /// <value>The data table form.</value>
17        public DataTable DataTableForm
18        {
19            get { return m_dataTable; }
20        }
21         private void AddObjectRowToListTable(IDataObject p_dataObject)
22        {
23            if (m_dataTable == null)
24                m_dataTable = p_dataObject.DataContainer.Clone();
25            DataRow m_newRow = m_dataTable.NewRow();
26
27
28            m_newRow.ItemArray = p_dataObject.ObjectRow.ItemArray;
29            /**//***********************************************
30            * 使用上面 代碼時間性能會比下面的高一倍
31            * for (int i = 0; i < p_dataObject.ObjectRow.ItemArray.Length; i++)
32               {
33                m_newRow[i] = p_dataObject.ObjectRow.ItemArray[i];
34                }
35            * ********************************************/
36
37            m_dataTable.Rows.Add(m_newRow);
38            p_dataObject.ObjectRow.Delete ();
39            p_dataObject.ObjectRow.Table.AcceptChanges();
40             p_dataObject.ObjectRow = m_newRow;
41        }
42        IList Members#region IList Members
43
44        /**//// <summary>
45         /// Adds an item to the <see cref="T:System.Collections.IList"></see>.
46        /// </summary>
47        /// <param name="value">The <see cref="T:System.Object"></see> to add to the <see cref="T:System.Collections.IList"></see>.</param>
48        /// <returns>
49        /// The position into which the new element was inserted.
50        /// </returns>
51        /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.IList"></see> is read-only.-or- The <see cref="T:System.Collections.IList"></see> has a fixed size. </exception>
52         public int Add(object value)
53        {
54             AddObjectRowToListTable((IDataObject)value);
55            return this.m_list.Add(value);
56        }
57
58        /**//// <summary>
59        /// Removes all items from the <see cref="T:System.Collections.IList"></see>.
60        /// </summary>
61        /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.IList"></see> is read-only. </exception>
62         public void Clear()
63        {
64            this.m_list.Clear();
65            this.DataTableForm.Clear();
66         }
67
68        /**//// <summary>
69        /// Determines whether the <see cref="T:System.Collections.IList"></see> contains a specific value.
70        /// </summary>
71        /// <param name="value">The <see cref="T:System.Object"></see> to locate in the <see cref="T:System.Collections.IList"></see>.</param>
72        /// <returns>
73        /// true if the <see cref="T:System.Object"></see> is found in the <see cref="T:System.Collections.IList"></see>; otherwise, false.
74        /// </returns>
75        public bool Contains(object value)
76        {
77            return m_list.Contains(value);
78        }
79
80        /**//// <summary>
81        /// Determines the index of a specific item in the <see cref="T:System.Collections.IList"></see>.
82        /// </summary>
83        /// <param name="value">The <see cref="T:System.Object"></see> to locate in the <see cref="T:System.Collections.IList"></see>.</param>
84        /// <returns>
85        /// The index of value if found in the list; otherwise, -1.
86        /// </returns>
87        public int IndexOf(object value)
88        {
89            return m_list.IndexOf(value);
90         }
91
92        /**//// <summary>
93        /// Inserts an item to the <see cref="T:System.Collections.IList"></see> at the specified index.
94        /// </summary>
95        /// <param name="index">The zero-based index at which value should be inserted.</param>
96         /// <param name="value">The <see cref="T:System.Object"></see> to insert into the <see cref="T:System.Collections.IList"></see>.</param>
97        /// <exception cref="T:System.ArgumentOutOfRangeException">index is not a valid index in the <see cref="T:System.Collections.IList"></see>. </exception>
98         /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.IList"></see> is read-only.-or- The <see cref="T:System.Collections.IList"></see> has a fixed size. </exception>
99         /// <exception cref="T:System.NullReferenceException">value is null reference in the <see cref="T:System.Collections.IList"></see>.</exception>
100        public void Insert(int index, object value)
101        {
102             this.m_list.Insert(index, value);
103            AddObjectRowToListTable ((IDataObject)value);
104        }
105
106        /**//// <summary>
107        /// Gets a value indicating whether the <see cref="T:System.Collections.IList"></see> has a fixed size.
108        /// </summary>
109        /// <value></value>
110        /// <returns>true if the <see cref="T:System.Collections.IList"></see> has a fixed size; otherwise, false.</returns>
111        public bool IsFixedSize
112        {
113            get { return false; }
114         }
115
116        /**//// <summary>
117        /// Gets a value indicating whether the <see cref="T:System.Collections.IList"></see> is read-only.
118        /// </summary>
119        /// <value></value>
120        /// <returns>true if the <see cref="T:System.Collections.IList"></see> is read-only; otherwise, false.</returns>
121        public bool IsReadOnly
122        {
123            get { return false; }
124         }
125
126        /**//// <summary>
127        /// Removes the first occurrence of a specific object from the <see cref="T:System.Collections.IList"></see>.
128        /// </summary>
129        /// <param name="value">The <see cref="T:System.Object"></see> to remove from the <see cref="T:System.Collections.IList"></see>.</param>
130        /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.IList"></see> is read-only.-or- The <see cref="T:System.Collections.IList"></see> has a fixed size. </exception>
131        public void Remove(object value)
132         {
133            ((IDataObject)value).ObjectRow.Delete();
134             this.m_list.Remove(value);
135        }
136
137        /**//// <summary>
138        /// Removes the <see cref="T:System.Collections.IList"></see> item at the specified index.
139         /// </summary>
140        /// <param name="index">The zero- based index of the item to remove.</param>
141        /// <exception cref="T:System.ArgumentOutOfRangeException">index is not a valid index in the <see cref="T:System.Collections.IList"></see>. </exception>
142        /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.IList"></see> is read-only.-or- The <see cref="T:System.Collections.IList"></see> has a fixed size. </exception>
143        public void RemoveAt(int index)
144        {
145            ((IDataObject)this.m_list[index]).ObjectRow.Delete();
146             this.m_list.RemoveAt(index);
147        }
148
149         /**//// <summary>
150        /// Gets or sets the <see cref="T:Object"/> at the specified index.
151        /// </summary>
152        /// <value></value>
153        public object this[int index]
154        {
155            get { return this.m_list[index]; }
156            set
157            {
158                throw new Exception("The method or operation is not implemented.");
159            }
160        }
161
162         #endregion
163
164        ICollection Members#region ICollection Members
165
166        /**//// <summary>
167        /// Copies the elements of the <see cref="T:System.Collections.ICollection"></see> to an <see cref="T:System.Array"></see>, starting at a particular <see cref="T:System.Array"></see> index.
168        /// </summary>
169        /// <param name="array">The one-dimensional <see cref="T:System.Array"></see> that is the destination of the elements copied from <see cref="T:System.Collections.ICollection"></see>. The <see cref="T:System.Array"></see> must have zero-based indexing.</param>
170         /// <param name="index">The zero-based index in array at which copying begins.</param>
171        /// <exception cref="T:System.ArgumentNullException">array is null. </exception>
172         /// <exception cref="T:System.ArgumentOutOfRangeException">index is less than zero. </exception>
173        /// <exception cref="T:System.ArgumentException">array is multidimensional.-or- index is equal to or greater than the length of array.-or- The number of elements in the source <see cref="T:System.Collections.ICollection"></see> is greater than the available space from index to the end of the destination array. </exception>
174        /// <exception cref="T:System.InvalidCastException">The type of the source <see cref="T:System.Collections.ICollection"></see> cannot be cast automatically to the type of the destination array. </exception>
175        public void CopyTo (Array array, int index)
176        {
177            this.m_list.CopyTo(array, index);
178        }
179
180        /**//// <summary>
181        /// Gets the number of elements contained in the <see cref="T:System.Collections.ICollection"></see>.
182        /// </summary>
183        /// <value></value>
184        /// <returns>The number of elements contained in the <see cref="T:System.Collections.ICollection"></see>.</returns>
185         public int Count
186        {
187            get { return this.m_list.Count; }
188        }
189
190        /**//// <summary>
191        /// Gets a value indicating whether access to the <see cref="T:System.Collections.ICollection"></see> is synchronized (thread safe).
192        /// </summary>
193        /// <value></value>
194        /// <returns>true if access to the <see cref="T:System.Collections.ICollection"></see> is synchronized (thread safe); otherwise, false.</returns>
195        public bool IsSynchronized
196        {
197            get { return false; }
198        }
199
200        /**//// <summary>
201         /// Gets an object that can be used to synchronize access to the <see cref="T:System.Collections.ICollection"></see>.
202        /// </summary>
203        /// <value></value>
204        /// <returns>An object that can be used to synchronize access to the <see cref="T:System.Collections.ICollection"></see>.</returns>
205         public object SyncRoot
206        {
207            get { return this.m_list.SyncRoot; }
208        }
209
210        #endregion
211
212        IEnumerable Members#region IEnumerable Members
213
214        /**//// <summary>
215        /// Returns an enumerator that iterates through a collection.
216        /// </summary>
217        /// <returns>
218        /// An <see cref="T:System.Collections.IEnumerator"></see> object that can be used to iterate through the collection.
219        /// </returns>
220         public IEnumerator GetEnumerator()
221        {
222            return m_list.GetEnumerator();
223        }
224
225        #endregion
226
227        protected ObjectList1(SerializationInfo info, StreamingContext context)
228        {
229            m_dataTable = info.GetValue("DataTable", typeof(DataTable)) as DataTable;
230            Type m_dataObjectType = info.GetValue("DataObjectType", typeof(Type)) as Type;
231             if (m_dataObjectType != null)
232            {
233                 m_list = new ArrayList();
234                foreach (DataRow m_dr in m_dataTable.Rows)
235                {
236                     m_list.Add(Activator.CreateInstance (m_dataObjectType,m_dr));
237                }
238             }
239        }
240        ISerializable Members#region ISerializable Members
241
242        public void GetObjectData(SerializationInfo info, StreamingContext context)
243        {
244            if (m_list.Count >= 0)
245            {
246                info.AddValue("DataObjectType", this.m_list[0].GetType());
247            }
248
249            info.AddValue("DataTable", this.m_dataTable, typeof (DataTable));
250        }
251
252        #endregion
253    }

上面的數據類肯定還存在一些問題,目前沒有更深入地去研究,有些地方可能還不是很合理,隨著應 用的深入,仍需要做一些改進。最後,如果認為這樣使用很不爽,不能做到強類型的引用。所有的對象都 只能認識到DataObjectBase這一級類型(因為所有的數據類都是這個抽象裡繼承下來)。我們可以定義一個 泛型的集合對它進行包裝,這裡就不多做介紹了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved