与DotNet数据对象结合的自定义数据对象设计 (二) 数据集合与DataTable

在上篇Blog中介绍了如何定义一个与DataRow相结合的数据类,那么本篇将介绍如何定义一个与DataTable对应的数据集合。

DotNet中提供了一个CollectionBase作为我们定义强类型的数据集合的抽象类,在DotNet1.1中要定义一个强类型的数据集合就必须为每一种数据类定义一个对应的数据集合,在2.0中增加了泛型的功能后,这个问题得到了解决。又由于在目前的Ibatisnet版本中还不支持泛型的功能,所以数据集合可以选择从ArrayListCollectionBase继承下来。但是不管是ArrayList还是CollectionBase都不支持序列化,也是他们都有没有Serializable属性,那么实现的数据集合也将无法实现序列化,所以这边选择直接实现IList接口,内部再实例化一个ArrayList做为数据容器。类的定义如下:

public class ObjectList : IList, ISerializable{}

还有一需要解决的问题是,数据类如何与DataTable对应起来呢?在数据类定义一个DataTable的属性和内部变量,做为存储数据的容器。

 1 private  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,而数据不动的办法就是将源RowItemArray属性赋值给目的的ItemArray。经过测试,这样做可以减少1倍以上的时间成本(内存成本也一样)。

具体的添加方法如下:

 1 private   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接口如下:

 1 public   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

同时增加一个反序列化的构造函数

 1 protected  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
163
164        ICollection Members
211
212        IEnumerable Members
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
253    }

上面的数据类肯定还存在一些问题,目前没有更深入地去研究,有些地方可能还不是很合理,随着应用的深入,仍需要做一些改进。最后,如果认为这样使用很不爽,不能做到强类型的引用。所有的对象都只能认识到DataObjectBase这一级类型(因为所有的数据类都是这个抽象里继承下来)。我们可以定义一个泛型的集合对它进行包装,这里就不多做介绍了。

快速索引
    与DotNet数据对象结合的自定义数据对象设计 (一) 数据对象与DataRow

你可能感兴趣的:(Datatable)