2004-06-08 Umadevi S <sumadevi@novell.com>
[mono.git] / mcs / class / System.Data / System.Data.Common / DataContainer.cs
1 using System;
2 using System.Collections;
3
4 namespace System.Data.Common
5 {
6         internal abstract class AbstractDataContainer
7         {
8                 #region Fields
9
10                 BitArray _nullValues;
11                 System.Type _type;
12                 DataColumn _column;
13
14                 #endregion //Fields
15
16                 #region Properties
17
18                 internal abstract object this[int index] {
19                         get;
20                         set;
21                 }
22
23                 internal virtual int Capacity {
24                         get { 
25                                 return (_nullValues != null) ? _nullValues.Count : 0; 
26                         }
27                         set { 
28                                 if (_nullValues == null) {
29                                         _nullValues = new BitArray(value);
30                                 }
31                                 else {
32                                         _nullValues.Length = value;
33                                 }
34                         }
35                 }
36
37                 internal Type Type {
38                         get {
39                                 return _type;
40                         }
41                 }
42
43                 protected DataColumn Column {
44                         get {
45                                 return _column;
46                         }
47                 }
48
49                 #endregion //Properties
50
51                 #region Methods
52
53                 internal static AbstractDataContainer CreateInstance(Type type, DataColumn column)
54                 {
55                         AbstractDataContainer container;
56                         switch (Type.GetTypeCode(type)) {
57                                 case TypeCode.Int16 :
58                                         container = new Int16DataContainer();
59                                         break;
60                                 case TypeCode.Int32 : 
61                                         container = new Int32DataContainer();
62                                         break;
63                                 case TypeCode.Int64 :
64                                         container = new Int64DataContainer();
65                                         break;
66                                 case TypeCode.String :
67                                         container = new StringDataContainer();
68                                         break;
69                                 case TypeCode.Boolean:
70                                         container = new BitDataContainer();
71                                         break;
72                                 case TypeCode.Byte :
73                                         container = new ByteDataContainer();
74                                         break;
75                                 //case TypeCode.Char :
76                                 case TypeCode.DateTime :
77                                         container = new DateTimeDataContainer();
78                                         break;
79                                 //case TypeCode.Decimal :
80                                 case TypeCode.Double :
81                                         container = new DoubleDataContainer();
82                                         break;
83                                 //case TypeCode.SByte :
84                                 case TypeCode.Single :
85                                         container = new SingleDataContainer();
86                                         break;
87                                 //case TypeCode.UInt16 :
88                                 //case TypeCode.UInt32 :
89                                 //case TypeCode.UInt64 :
90                                 default :
91                                         container = new ObjectDataContainer();
92                                         break;
93                         }
94                         container._type = type;
95                         container._column = column;
96                         return container;
97                 }
98
99                 internal bool IsNull(int index)
100                 {
101                         return (_nullValues != null) ? _nullValues[index] : true;
102                 }
103
104                 protected void SetNull(int index,bool isNull)
105                 {
106                         _nullValues[index] = isNull;
107                 }
108
109                 internal virtual void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
110                 {
111                         _nullValues[toIndex] = fromContainer._nullValues[fromIndex];
112                 }
113
114                 internal virtual void CopyValue(int fromIndex, int toIndex)
115                 {
116                         _nullValues[toIndex] = _nullValues[fromIndex];
117                 }
118
119                 internal virtual void SetItemFromDataRecord(int index, IDataRecord record, int field)
120                 {
121                         SetNull(index,record.IsDBNull(field));
122                 }
123
124                 protected int CompareNulls(int index1, int index2)
125                 {
126                         bool null1 = IsNull(index1);
127                         bool null2 = IsNull(index2);
128
129                         if ( null1 ^ null2 ) {
130                                 return null1 ? -1 : 1;
131                         }
132                         else {
133                                 return 0;
134                         }
135                 }
136
137                 internal abstract int CompareValues(int index1, int index2);
138
139                 #endregion //Methods
140
141                 sealed class Int16DataContainer : AbstractDataContainer
142                 {
143                         #region Fields
144                 
145                         short[] _values;
146
147                         #endregion //Fields
148
149                         #region Properties
150
151                         internal override object this[int index] {
152                                 get {
153                                         if (IsNull(index)) {
154                                                 return DBNull.Value;
155                                         }
156                                         else {
157                                                 return _values[index];
158                                         }
159                                 }
160                                 set {
161                                         bool isDbNull = (value ==  DBNull.Value);
162                                         if (value == null || isDbNull) {
163                                                 SetValue(index,0);
164                                         }
165                                         else if( value is short ) {
166                                                 SetValue(index,(short)value);
167                                         }
168                                         else {
169                                                 SetValue(index,Convert.ToInt16(value));
170                                         }
171                                         SetNull(index,isDbNull);
172                                 }
173                         }
174
175                         internal override int Capacity {
176                                 set {
177                                         base.Capacity = value;
178                                         if (_values == null) {
179                                                 _values = new short[value];
180                                         }
181                                         else {
182                                                 short[] tmp = new short[value];
183                                                 Array.Copy(_values,0,tmp,0,_values.Length);
184                                                 _values = tmp;
185                                         }
186                                 }
187                         }
188
189                         #endregion //Properties
190
191                         #region Methods
192                         
193                         private void SetValue(int index, short value)
194                         {
195                                 _values[index] = value;
196                         }
197
198                         internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
199                         {
200                                 // if exception thrown, it should be caught 
201                                 // in the  caller method
202                                 SetValue(index,record.GetInt16(field));
203                                 base.SetItemFromDataRecord(index,record,field);
204                         }
205
206                         internal override void CopyValue(int fromIndex, int toIndex)
207                         {
208                                 base.CopyValue(fromIndex, toIndex);
209                                 _values[toIndex] = _values[fromIndex];
210                         }
211
212                         internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
213                         {
214                                 base.CopyValue(fromContainer, fromIndex, toIndex);
215                                 _values[toIndex] = ((Int16DataContainer)fromContainer)._values[fromIndex];
216                         }
217
218                         internal override int CompareValues(int index1, int index2)
219                         {
220                                 short s1 = _values[index1];
221                                 short s2 = _values[index2];
222
223                                 if ( s1 == 0 && s2 == 0 ) {
224                                         int cn = CompareNulls(index1, index2);
225                                         return cn;
226                                 }
227
228                                 bool b1 = IsNull(index1);
229                                 bool b2 = IsNull(index2);
230                                 
231                                 if ( s1 == 0 && b1 ) {
232                                         return -1;
233                                 }
234
235                                 if ( s2 == 0 && b2 ) {
236                                         return 1;
237                                 }
238
239                                 if ( s1 <= s2 ) {
240                                         return ( s1 != s2 ) ? -1 : 0;
241                                 }
242                                 return 1;
243                         }
244
245                         #endregion //Methods
246                 }
247
248                 sealed class Int32DataContainer : AbstractDataContainer
249                 {
250                         #region Fields
251                 
252                         int[] _values;
253
254                         #endregion //Fields
255
256                         #region Properties
257
258                         internal override object this[int index] {
259                                 get {
260                                         if (IsNull(index)) {
261                                                 return DBNull.Value;
262                                         }
263                                         else {
264                                                 return _values[index];
265                                         }
266                                 }
267                                 set {
268                                         bool isDbNull = (value ==  DBNull.Value);
269                                         if (value == null || isDbNull) {
270                                                 SetValue(index,0);
271                                         }
272                                         else if( value is int ) {
273                                                 SetValue(index,(int)value);
274                                         }
275                                         else {
276                                                 SetValue(index,Convert.ToInt32(value));
277                                         }
278                                         SetNull(index,isDbNull);
279                                 }
280                         }
281
282                         internal override int Capacity {
283                                 set {
284                                         base.Capacity = value;
285                                         if (_values == null) {
286                                                 _values = new int[value];
287                                         }
288                                         else {
289                                                 int[] tmp = new int[value];
290                                                 Array.Copy(_values,0,tmp,0,_values.Length);
291                                                 _values = tmp;
292                                         }
293                                 }
294                         }
295
296                         #endregion //Properties
297
298                         #region Methods
299                         
300                         private void SetValue(int index, int value)
301                         {
302                                 _values[index] = value;
303                         }
304
305                         internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
306                         {
307                                 // if exception thrown, it should be caught 
308                                 // in the  caller method
309                                 SetValue(index,record.GetInt32(field));
310                                 base.SetItemFromDataRecord(index,record,field);
311                         }
312
313                         internal override void CopyValue(int fromIndex, int toIndex)
314                         {
315                                 base.CopyValue(fromIndex, toIndex);
316                                 _values[toIndex] = _values[fromIndex];
317                         }
318
319                         internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
320                         {
321                                 base.CopyValue(fromContainer, fromIndex, toIndex);
322                                 _values[toIndex] = ((Int32DataContainer)fromContainer)._values[fromIndex];
323                         }
324
325                         internal override int CompareValues(int index1, int index2)
326                         {
327                                 int i1 = _values[index1];
328                                 int i2 = _values[index2];
329
330                                 if ( i1 == 0 && i2 == 0 ) {
331                                         int cn = CompareNulls(index1, index2);
332                                         return cn;
333                                 }
334
335                                 bool b1 = IsNull(index1);
336                                 bool b2 = IsNull(index2);
337                                 
338                                 if ( i1 == 0 && b1 ) {
339                                         return -1;
340                                 }
341
342                                 if ( i2 == 0 && b2 ) {
343                                         return 1;
344                                 }
345
346                                 if ( i1 <= i2 ) {
347                                         return ( i1 != i2 ) ? -1 : 0;
348                                 }
349                                 return 1;
350                         }
351
352                         #endregion //Methods
353                 }
354
355                 sealed class Int64DataContainer : AbstractDataContainer
356                 {
357                         #region Fields
358                 
359                         long[] _values;
360
361                         #endregion //Fields
362
363                         #region Properties
364
365                         internal override object this[int index] {
366                                 get {
367                                         if (IsNull(index)) {
368                                                 return DBNull.Value;
369                                         }
370                                         else {
371                                                 return _values[index];
372                                         }
373                                 }
374                                 set {
375                                         bool isDbNull = (value ==  DBNull.Value);
376                                         if (value == null || isDbNull) {
377                                                 SetValue(index,0);
378                                         }
379                                         else if( value is long ) {
380                                                 SetValue(index,(long)value);
381                                         }
382                                         else {
383                                                 SetValue(index,Convert.ToInt64(value));
384                                         }
385                                         SetNull(index,isDbNull);
386                                 }
387                         }
388
389                         internal override int Capacity {
390                                 set {
391                                         base.Capacity = value;
392                                         if (_values == null) {
393                                                 _values = new long[value];
394                                         }
395                                         else {
396                                                 long[] tmp = new long[value];
397                                                 Array.Copy(_values,0,tmp,0,_values.Length);
398                                                 _values = tmp;
399                                         }
400                                 }
401                         }
402
403                         #endregion //Properties
404
405                         #region Methods
406                         
407                         private void SetValue(int index, long value)
408                         {
409                                 _values[index] = value;
410                         }
411
412                         internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
413                         {
414                                 // if exception thrown, it should be caught 
415                                 // in the  caller method
416                                 SetValue(index,record.GetInt64(field));
417                                 base.SetItemFromDataRecord(index,record,field);
418                         }
419
420                         internal override void CopyValue(int fromIndex, int toIndex)
421                         {
422                                 base.CopyValue(fromIndex, toIndex);
423                                 _values[toIndex] = _values[fromIndex];
424                         }
425
426                         internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
427                         {
428                                 base.CopyValue(fromContainer, fromIndex, toIndex);
429                                 _values[toIndex] = ((Int64DataContainer)fromContainer)._values[fromIndex];
430                         }
431
432                         internal override int CompareValues(int index1, int index2)
433                         {
434                                 long l1 = _values[index1];
435                                 long l2 = _values[index2];
436
437                                 if ( l1 == 0 || l2 == 0 ) {
438                                         int cn = CompareNulls(index1, index2);
439                                         if (cn != 0) {
440                                                 return cn;
441                                         }
442                                 }
443
444                                 if ( l1 <= l2 ) {
445                                         return ( l1 != l2 ) ? -1 : 0;
446                                 }
447                                 return 1;
448                         }
449
450                         #endregion //Methods
451                 }
452
453                 sealed class SingleDataContainer : AbstractDataContainer
454                 {
455                         #region Fields
456                 
457                         float[] _values;
458
459                         #endregion //Fields
460
461                         #region Properties
462
463                         internal override object this[int index] {
464                                 get {
465                                         if (IsNull(index)) {
466                                                 return DBNull.Value;
467                                         }
468                                         else {
469                                                 return _values[index];
470                                         }
471                                 }
472                                 set {
473                                         bool isDbNull = (value ==  DBNull.Value);
474                                         if (value == null || isDbNull) {
475                                                 SetValue(index,0);
476                                         }
477                                         else if( value is float ) {
478                                                 SetValue(index,(float)value);
479                                         }
480                                         else {
481                                                 SetValue(index,Convert.ToSingle(value));
482                                         }
483                                         SetNull(index,isDbNull);
484                                 }
485                         }
486
487                         internal override int Capacity {
488                                 set {
489                                         base.Capacity = value;
490                                         if (_values == null) {
491                                                 _values = new float[value];
492                                         }
493                                         else {
494                                                 float[] tmp = new float[value];
495                                                 Array.Copy(_values,0,tmp,0,_values.Length);
496                                                 _values = tmp;
497                                         }
498                                 }
499                         }
500
501                         #endregion //Properties
502
503                         #region Methods
504                         
505                         private void SetValue(int index, float value)
506                         {
507                                 _values[index] = value;
508                         }
509
510                         internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
511                         {
512                                 // if exception thrown, it should be caught 
513                                 // in the  caller method
514                                 SetValue(index,record.GetFloat(field));
515                                 base.SetItemFromDataRecord(index,record,field);
516                         }
517
518                         internal override void CopyValue(int fromIndex, int toIndex)
519                         {
520                                 base.CopyValue(fromIndex, toIndex);
521                                 _values[toIndex] = _values[fromIndex];
522                         }
523
524                         internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
525                         {
526                                 base.CopyValue(fromContainer, fromIndex, toIndex);
527                                 _values[toIndex] = ((SingleDataContainer)fromContainer)._values[fromIndex];
528                         }
529
530                         internal override int CompareValues(int index1, int index2)
531                         {
532                                 float f1 = _values[index1];
533                                 float f2 = _values[index2];
534
535                                 if ( f1 == 0 || f2 == 0 ) {
536                                         int cn = CompareNulls(index1, index2);
537                                         if (cn != 0) {
538                                                 return cn;
539                                         }
540                                 }
541
542                                 if ( f1 <= f2 ) {
543                                         return ( f1 != f2 ) ? -1 : 0;
544                                 }
545                                 return 1;
546                         }
547
548                         #endregion //Methods
549                 }
550
551                 sealed class DoubleDataContainer : AbstractDataContainer
552                 {
553                         #region Fields
554                 
555                         double[] _values;
556
557                         #endregion //Fields
558
559                         #region Properties
560
561                         internal override object this[int index] {
562                                 get {
563                                         if (IsNull(index)) {
564                                                 return DBNull.Value;
565                                         }
566                                         else {
567                                                 return _values[index];
568                                         }
569                                 }
570                                 set {
571                                         bool isDbNull = (value ==  DBNull.Value);
572                                         if (value == null || isDbNull) {
573                                                 SetValue(index,0);
574                                         }
575                                         else if( value is double ) {
576                                                 SetValue(index,(double)value);
577                                         }
578                                         else {
579                                                 SetValue(index,Convert.ToDouble(value));
580                                         }
581                                         SetNull(index,isDbNull);
582                                 }
583                         }
584
585                         internal override int Capacity {
586                                 set {
587                                         base.Capacity = value;
588                                         if (_values == null) {
589                                                 _values = new double[value];
590                                         }
591                                         else {
592                                                 double[] tmp = new double[value];
593                                                 Array.Copy(_values,0,tmp,0,_values.Length);
594                                                 _values = tmp;
595                                         }
596                                 }
597                         }
598
599                         #endregion //Properties
600
601                         #region Methods
602                         
603                         private void SetValue(int index, double value)
604                         {
605                                 _values[index] = value;
606                         }
607
608                         internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
609                         {
610                                 // if exception thrown, it should be caught 
611                                 // in the  caller method
612                                 SetValue(index,record.GetDouble(field));
613                                 base.SetItemFromDataRecord(index,record,field);
614                         }
615
616                         internal override void CopyValue(int fromIndex, int toIndex)
617                         {
618                                 base.CopyValue(fromIndex, toIndex);
619                                 _values[toIndex] = _values[fromIndex];
620                         }
621
622                         internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
623                         {
624                                 base.CopyValue(fromContainer, fromIndex, toIndex);
625                                 _values[toIndex] = ((DoubleDataContainer)fromContainer)._values[fromIndex];
626                         }
627
628                         internal override int CompareValues(int index1, int index2)
629                         {
630                                 double d1 = _values[index1];
631                                 double d2 = _values[index2];
632
633                                 if ( d1 == 0 || d2 == 0 ) {
634                                         int cn = CompareNulls(index1, index2);
635                                         if (cn != 0) {
636                                                 return cn;
637                                         }
638                                 }
639
640                                 if ( d1 <= d2 ) {
641                                         return ( d1 != d2 ) ? -1 : 0;
642                                 }
643                                 return 1;
644                         }
645
646                         #endregion //Methods
647                 }
648
649                 sealed class ByteDataContainer : AbstractDataContainer
650                 {
651                         #region Fields
652                 
653                         byte[] _values;
654
655                         #endregion //Fields
656
657                         #region Properties
658
659                         internal override object this[int index] {
660                                 get {
661                                         if (IsNull(index)) {
662                                                 return DBNull.Value;
663                                         }
664                                         else {
665                                                 return _values[index];
666                                         }
667                                 }
668                                 set {
669                                         bool isDbNull = (value ==  DBNull.Value);
670                                         if (value == null || isDbNull) {
671                                                 SetValue(index,0);
672                                         }
673                                         else if( value is byte ) {
674                                                 SetValue(index,(byte)value);
675                                         }
676                                         else {
677                                                 SetValue(index,Convert.ToByte(value));
678                                         }
679                                         SetNull(index,isDbNull);
680                                 }
681                         }
682
683                         internal override int Capacity {
684                                 set {
685                                         base.Capacity = value;
686                                         if (_values == null) {
687                                                 _values = new byte[value];
688                                         }
689                                         else {
690                                                 byte[] tmp = new byte[value];
691                                                 Array.Copy(_values,0,tmp,0,_values.Length);
692                                                 _values = tmp;
693                                         }
694                                 }
695                         }
696
697                         #endregion //Properties
698
699                         #region Methods
700                         
701                         private void SetValue(int index, byte value)
702                         {
703                                 _values[index] = value;
704                         }
705
706                         internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
707                         {
708                                 // if exception thrown, it should be caught 
709                                 // in the  caller method
710                                 SetValue(index,record.GetByte(field));
711                                 base.SetItemFromDataRecord(index,record,field);
712                         }
713
714                         internal override void CopyValue(int fromIndex, int toIndex)
715                         {
716                                 base.CopyValue(fromIndex, toIndex);
717                                 _values[toIndex] = _values[fromIndex];
718                         }
719
720                         internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
721                         {
722                                 base.CopyValue(fromContainer, fromIndex, toIndex);
723                                 _values[toIndex] = ((ByteDataContainer)fromContainer)._values[fromIndex];
724                         }
725
726                         internal override int CompareValues(int index1, int index2)
727                         {
728                                 byte b1 = _values[index1];
729                                 byte b2 = _values[index2];
730
731                                 if ( b1 == 0 || b2 == 0 ) {
732                                         int cn = CompareNulls(index1, index2);
733                                         if (cn != 0) {
734                                                 return cn;
735                                         }
736                                 }
737
738                                 if ( b1 <= b2 ) {
739                                         return ( b1 != b2 ) ? -1 : 0;
740                                 }
741                                 return 1;
742                         }
743
744                         #endregion //Methods
745                 }
746
747                 sealed class BitDataContainer : AbstractDataContainer
748                 {
749                         #region Fields
750                 
751                         bool[] _values;
752
753                         #endregion //Fields
754
755                         #region Properties
756
757                         internal override object this[int index] {
758                                 get {
759                                         bool isNull = IsNull(index);
760                                         if (isNull) {
761                                                 return DBNull.Value;
762                                         }
763                                         else {
764                                                 return _values[index];
765                                         }
766                                 }
767                                 set {
768                                         bool isDbNull = (value ==  DBNull.Value);
769                                         if (value == null || isDbNull) {
770                                                 SetValue(index,false);
771                                         }
772                                         else if( value is bool ) {
773                                                 SetValue(index,(bool)value);
774                                         }
775                                         else {
776                                                 SetValue(index,Convert.ToBoolean(value));
777                                         }
778                                         SetNull(index,isDbNull);
779                                 }
780                         }
781
782                         internal override int Capacity {
783                                 set {
784                                         base.Capacity = value;
785                                         if (_values == null) {
786                                                 _values = new bool[value];
787                                         }
788                                         else {
789                                                 bool[] tmp = new bool[value];
790                                                 Array.Copy(_values,0,tmp,0,_values.Length);
791                                                 _values = tmp;
792                                         }
793                                 }
794                         }
795
796                         #endregion //Properties
797
798                         #region Methods
799                         
800                         private void SetValue(int index, bool value)
801                         {
802                                 _values[index] = value;
803                         }
804
805                         internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
806                         {
807                                 // if exception thrown, it should be caught 
808                                 // in the  caller method
809                                 SetValue(index,record.GetBoolean(field));
810                         }
811
812                         internal override void CopyValue(int fromIndex, int toIndex)
813                         {
814                                 base.CopyValue(fromIndex, toIndex);
815                         }
816
817                         internal override int CompareValues(int index1, int index2)
818                         {
819                                 bool b1 = _values[index1];
820                                 bool b2 = _values[index2];
821
822                                 if ( b1 ^ b2 ) {
823                                         return b1 ? 1 : -1;
824                                 }
825                                 
826                                 if ( b1 ) {
827                                         return 0;
828                                 }
829
830                                 return CompareNulls(index1, index2);    
831                         }
832
833                         #endregion //Methods
834                 }
835
836                 class ObjectDataContainer : AbstractDataContainer
837                 {
838                         #region Fields
839                 
840                         object[] _values;
841
842                         #endregion //Fields
843
844                         #region Properties
845
846                         internal override object this[int index] {
847                                 get {
848                                         return _values[index];
849                                 }
850                                 set {
851                                         SetValue(index,value);
852                                         SetNull(index,value == DBNull.Value);
853                                 }
854                         }
855
856                         internal override int Capacity {
857                                 set {
858                                         base.Capacity = value;
859                                         if (_values == null) {
860                                                 _values = new object[value];
861                                         }
862                                         else {
863                                                 object[] tmp = new object[value];
864                                                 Array.Copy(_values,0,tmp,0,_values.Length);
865                                                 _values = tmp;
866                                         }
867                                 }
868                         }
869
870                         #endregion //Properties
871
872                         #region Methods
873                         
874                         protected virtual void SetValue(int index, object value)
875                         {
876                                 if(value == null) {
877                                         value = Column.DefaultValue;
878                                 }
879                                 _values[index] = value;
880                         }
881
882                         internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
883                         {
884                                 // if exception thrown, it should be caught 
885                                 // in the  caller method
886                                 SetValue(index,record.GetValue(field));
887                                 base.SetItemFromDataRecord(index,record,field);
888                         }
889
890                         internal override void CopyValue(int fromIndex, int toIndex)
891                         {
892                                 base.CopyValue(fromIndex, toIndex);
893                                 _values[toIndex] = _values[fromIndex];
894                         }
895
896                         internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
897                         {
898                                 base.CopyValue(fromContainer, fromIndex, toIndex);
899                                 _values[toIndex] = ((ObjectDataContainer)fromContainer)._values[fromIndex];
900                         }
901
902                         internal override int CompareValues(int index1, int index2)
903                         {
904                                 object obj1 = _values[index1];
905                                 object obj2 = _values[index2];
906                                 if(obj1 == obj2) {
907                                         return 0;
908                                 }
909                                 else if (obj1 is IComparable) {
910                                         try {
911                                                 return ((IComparable)obj1).CompareTo(obj2);
912                                         }
913                                         catch {
914                                                 //just suppress
915                                         }
916
917                                         if (obj2 is IComparable) {
918                                                 obj2 = Convert.ChangeType(obj2, Type.GetTypeCode(obj1.GetType()));
919                                                 return ((IComparable)obj1).CompareTo(obj2);
920                                         }
921                                 }
922
923                                 return String.Compare(obj1.ToString(), obj2.ToString());
924                         }
925
926                         #endregion //Methods
927          
928                 }
929
930                 sealed class StringDataContainer : ObjectDataContainer
931                 {
932                         #region Methods
933
934                         private void SetValue(int index, string value)
935                         {
936                                 if (value != null && Column.MaxLength >= 0 && Column.MaxLength < value.Length ) {
937                                         throw new ArgumentException("Cannot set column '" + Column.ColumnName + "' to '" + value + "'. The value violates the MaxLength limit of this column.");
938                                 }
939                                 base.SetValue(index,value);
940                         }
941                         
942                         protected override void SetValue(int index, object value)
943                         {
944                                 if ( value != null && value != DBNull.Value ) {
945                                         if ( value is string ) {
946                                                 SetValue(index, (string) value);
947                                         }
948                                         else {
949                                                 SetValue(index, Convert.ToString(value));
950                                         }
951                                         return;
952                                 }
953
954                                 base.SetValue(index, value);
955                         }
956
957                         internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
958                         {
959                                 // if exception thrown, it should be caught 
960                                 // in the  caller method
961                                 SetValue(index,record.GetString(field));
962                                 base.SetItemFromDataRecord(index,record,field);
963                         }
964
965                         internal override int CompareValues(int index1, int index2)
966                         {
967                                 bool isNull1 = IsNull(index1);
968                                 bool isNull2 = IsNull(index2);
969
970                                 if (isNull1) {
971                                         return isNull2 ? 0 : -1;
972                                 }
973                                 else {
974                                         if (isNull2) {
975                                                 return 1;
976                                         }
977                                 }
978                                 return String.Compare((string)this[index1], (string)this[index2], !Column.Table.CaseSensitive);
979                         }
980
981                         #endregion //Methods 
982                 }
983
984                 sealed class DateTimeDataContainer : ObjectDataContainer
985                 {
986                         #region Methods
987                         
988                         protected override void SetValue(int index, object value)
989                         {
990                                 if ( value != null && value != DBNull.Value && !(value is DateTime)) {
991                                         value = Convert.ToDateTime(value);
992                                 }
993
994                                 base.SetValue(index,value);
995                         }
996
997                         internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
998                         {
999                                 // if exception thrown, it should be caught 
1000                                 // in the  caller method
1001                                 base.SetValue(index,record.GetDateTime(field));
1002                                 base.SetItemFromDataRecord(index,record,field);
1003                         }
1004
1005                         internal override int CompareValues(int index1, int index2)
1006                         {
1007                                 bool isNull1 = IsNull(index1);
1008                                 bool isNull2 = IsNull(index2);
1009
1010                                 if (isNull1) {
1011                                         return isNull2 ? 0 : -1;
1012                                 }
1013                                 else {
1014                                         if (isNull2) {
1015                                                 return 1;
1016                                         }
1017                                 }
1018                                 return DateTime.Compare((DateTime)this[index1], (DateTime)this[index2]);
1019                         }
1020
1021                         #endregion //Methods 
1022                 }
1023         }
1024 }