X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem.Data%2FSystem.Data%2FDataRow.cs;h=cbc95c861ae1b5836f75fb6277d032ffd4e338ab;hb=b1ca844c7e7f2056b7be394d98842eea69c16f12;hp=49c59a922dbaa3a0e33b3ff3905fe701b4bc25c1;hpb=9919af677abb50e101e88fc4670c5746650688a3;p=mono.git diff --git a/mcs/class/System.Data/System.Data/DataRow.cs b/mcs/class/System.Data/System.Data/DataRow.cs index 49c59a922db..cbc95c861ae 100644 --- a/mcs/class/System.Data/System.Data/DataRow.cs +++ b/mcs/class/System.Data/System.Data/DataRow.cs @@ -7,6 +7,7 @@ // Tim Coleman // Ville Palo // Alan Tam Siu Lung +// Sureshkumar T // // (C) Ximian, Inc 2002 // (C) Daniel Morgan 2002, 2003 @@ -37,6 +38,7 @@ // using System; +using System.Data.Common; using System.Collections; using System.Globalization; using System.Xml; @@ -233,6 +235,82 @@ namespace System.Data { } } + /// + /// Sets the index into the container records for the original version. Apart + /// from that, it makes sure it pools the record used earlier if they are not + /// used by other versions. + /// + internal int Original + { + get { return _original;} + set { + if (_original == value) + return; + + if (_original >= 0 + && _current != _original + && _proposed != _original) + Table.RecordCache.DisposeRecord (_original); + _original = value; + } + } + + /// + /// Sets the index into the container records for the proposed version. Apart + /// from that, it makes sure it pools the record used earlier if they are not + /// used by other versions. + internal int Proposed + { + get { return _proposed;} + set { + if (_proposed == value) + return; + if (_proposed >= 0 + && _proposed != _current + && _proposed != _original) + Table.RecordCache.DisposeRecord (_proposed); + _proposed = value; + } + } + + /// + /// Sets the index into the container records for the current version. Apart + /// from that, it makes sure it pools the record used earlier if they are not + /// used by other versions. + internal int Current + { + get { return _current;} + set { + if (_current == value) + return; + if (_current >= 0 + && _current != _original + && _current != _proposed) + Table.RecordCache.DisposeRecord (_current); + _current = value; + } + } + + /// + /// Set a value for the column into the offset specified by the version.
+ /// If the value is auto increment or null, necessary auto increment value + /// or the default value will be used. + ///
+ internal void SetValue (int column, object value, int version) + { + DataColumn dc = Table.Columns[column]; + + if (value == null && ! dc.AutoIncrement) // set default value / auto increment + value = dc.DefaultValue; + + Table.ChangingDataColumn (this, dc, value); + CheckValue (value, dc); + if ( ! dc.AutoIncrement) + dc [version] = value; + else if (_proposed >= 0 && _proposed != version) // proposed holds the AI + dc [version] = dc [_proposed]; + } + /// /// Gets the data stored in the column, specified by index and version of the data to /// retrieve. @@ -250,15 +328,15 @@ namespace System.Data { object o = column.CompiledExpression.Eval (this); return Convert.ChangeType (o, column.DataType); } + + if (rowState == DataRowState.Detached && version == DataRowVersion.Default && _proposed < 0) + throw new RowNotInTableException("This row has been removed from a table and does not have any data. BeginEdit() will allow creation of new data in this row."); int recordIndex = IndexFromVersion(version); if (recordIndex >= 0) { return column[recordIndex]; } - - if (rowState == DataRowState.Detached && version == DataRowVersion.Default && _proposed < 0) - throw new RowNotInTableException("This row has been removed from a table and does not have any data. BeginEdit() will allow creation of new data in this row."); throw new VersionNotFoundException (Locale.GetText ("There is no " + version.ToString () + " data to access.")); } @@ -310,6 +388,10 @@ namespace System.Data { } } + internal bool IsEditing { + get { return editing; } + } + /// /// Gets the current state of the row in regards to its relationship to the /// DataRowCollection. @@ -354,7 +436,7 @@ namespace System.Data { } } - #endregion + #endregion // Properties #region Methods @@ -404,9 +486,6 @@ namespace System.Data { internal void SetValuesFromDataRecord(IDataRecord record, int[] mapping) { - if ( mapping.Length > Table.Columns.Count) - throw new ArgumentException (); - // bool orginalEditing = editing; // if (!orginalEditing) { // BeginEdit (); @@ -417,8 +496,14 @@ namespace System.Data { } try { - for(int i=0; i < mapping.Length; i++) { + for(int i=0; i < Table.Columns.Count; i++) { DataColumn column = Table.Columns[i]; + if (mapping [i] < 0) { // no mapping + if (! column.AutoIncrement) + column.DataContainer [_proposed] = column.DefaultValue; + continue; + } + column.DataContainer.SetItemFromDataRecord(_proposed, record,mapping[i]); if ( column.AutoIncrement ) { column.UpdateAutoIncrementValue(column.DataContainer.GetInt64(_proposed)); @@ -489,9 +574,8 @@ namespace System.Data { DataColumn column = _table.Columns[columnName]; _table.ChangingDataColumn (this, column, val); - if (_original < 0 || _original == _current) { - // really add a row cache, if _original is not there & - // make row modified + if (_original < 0 || _original == _current) { + // This really creates a new record version if one does not exist _original = Table.RecordCache.NewRecord(); } CheckValue (val, column); @@ -521,10 +605,8 @@ namespace System.Data { throw new RowNotInTableException("Cannot perform this operation on a row not in the table."); } // Accept from detached - if (_original >= 0) { - Table.RecordCache.DisposeRecord(_original); - } - _original = _current; + if (_original != _current) + Original = Current; } /// @@ -787,7 +869,7 @@ namespace System.Data { /// public DataRow[] GetChildRows (DataRelation relation) { - return GetChildRows (relation, DataRowVersion.Current); + return GetChildRows (relation, DataRowVersion.Default); } /// @@ -808,12 +890,16 @@ namespace System.Data { if (relation == null) return new DataRow[0]; - if (this.Table == null || RowState == DataRowState.Detached) + //if (this.Table == null || RowState == DataRowState.Detached) + if (this.Table == null) throw new RowNotInTableException("This row has been removed from a table and does not have any data. BeginEdit() will allow creation of new data in this row."); if (relation.DataSet != this.Table.DataSet) throw new ArgumentException(); + if (_table != relation.ParentTable) + throw new InvalidConstraintException ("GetChildRow requires a row whose Table is " + relation.ParentTable + ", but the specified row's table is " + _table); + if (relation.ChildKeyConstraint != null) return GetChildRows (relation.ChildKeyConstraint, version); @@ -845,7 +931,9 @@ namespace System.Data { } if (allColumnsMatch) rows.Add(row); } - } + }else + throw new VersionNotFoundException("There is no " + version + " data to accces."); + DataRow[] result = relation.ChildTable.NewRowArray(rows.Count); rows.CopyTo(result, 0); return result; @@ -876,7 +964,7 @@ namespace System.Data { } } else { // if there is no index we search manualy. - int curIndex = IndexFromVersion(DataRowVersion.Current); + int curIndex = IndexFromVersion(DataRowVersion.Default); int tmpRecord = fkc.Table.RecordCache.NewRecord(); try { @@ -906,7 +994,8 @@ namespace System.Data { fkc.Table.RecordCache.DisposeRecord(tmpRecord); } } - } + }else + throw new VersionNotFoundException("There is no " + version + " data to accces."); DataRow[] result = fkc.Table.NewRowArray(rows.Count); rows.CopyTo(result, 0); @@ -967,7 +1056,7 @@ namespace System.Data { /// public DataRow GetParentRow (DataRelation relation) { - return GetParentRow (relation, DataRowVersion.Current); + return GetParentRow (relation, DataRowVersion.Default); } /// @@ -976,7 +1065,7 @@ namespace System.Data { /// public DataRow GetParentRow (string relationName) { - return GetParentRow (relationName, DataRowVersion.Current); + return GetParentRow (relationName, DataRowVersion.Default); } /// @@ -1004,7 +1093,7 @@ namespace System.Data { /// public DataRow[] GetParentRows (DataRelation relation) { - return GetParentRows (relation, DataRowVersion.Current); + return GetParentRows (relation, DataRowVersion.Default); } /// @@ -1013,7 +1102,7 @@ namespace System.Data { /// public DataRow[] GetParentRows (string relationName) { - return GetParentRows (relationName, DataRowVersion.Current); + return GetParentRows (relationName, DataRowVersion.Default); } /// @@ -1026,30 +1115,32 @@ namespace System.Data { if (relation == null) return new DataRow[0]; - if (this.Table == null || RowState == DataRowState.Detached) + if (this.Table == null) throw new RowNotInTableException("This row has been removed from a table and does not have any data. BeginEdit() will allow creation of new data in this row."); if (relation.DataSet != this.Table.DataSet) throw new ArgumentException(); + if (_table != relation.ChildTable) + throw new InvalidConstraintException ("GetParentRows requires a row whose Table is " + relation.ChildTable + ", but the specified row's table is " + _table); + ArrayList rows = new ArrayList(); DataColumn[] parentColumns = relation.ParentColumns; DataColumn[] childColumns = relation.ChildColumns; int numColumn = parentColumns.Length; if (HasVersion(version)) { Index indx = relation.ParentTable.GetIndexByColumns (parentColumns); - if (indx != null && - (Table == null || Table.DataSet == null || - Table.DataSet.EnforceConstraints)) { // get the child rows from the index + if (indx != null && + (Table == null || Table.DataSet == null || + Table.DataSet.EnforceConstraints)) { // get the child rows from the index Node[] childNodes = indx.FindAllSimple(childColumns, IndexFromVersion(version)); for (int i = 0; i < childNodes.Length; i++) { rows.Add (childNodes[i].Row); } } else { // no index so we have to search manualy. - int curIndex = IndexFromVersion(DataRowVersion.Current); + int curIndex = IndexFromVersion(DataRowVersion.Default); int tmpRecord = relation.ParentTable.RecordCache.NewRecord(); - try { for (int i = 0; i < numColumn; i++) { // according to MSDN: the DataType value for both columns must be identical. @@ -1077,7 +1168,8 @@ namespace System.Data { relation.ParentTable.RecordCache.DisposeRecord(tmpRecord); } } - } + }else + throw new VersionNotFoundException("There is no " + version + " data to accces."); DataRow[] result = relation.ParentTable.NewRowArray(rows.Count); rows.CopyTo(result, 0); @@ -1098,26 +1190,26 @@ namespace System.Data { /// public bool HasVersion (DataRowVersion version) { - switch (version) { - case DataRowVersion.Default: - if (rowState == DataRowState.Deleted && !_inExpressionEvaluation) - return false; - if (rowState == DataRowState.Detached) - return _proposed >= 0; - return true; - case DataRowVersion.Proposed: - if (rowState == DataRowState.Deleted && !_inExpressionEvaluation) - return false; - return _proposed >= 0; - case DataRowVersion.Current: - if ((rowState == DataRowState.Deleted && !_inExpressionEvaluation) || rowState == DataRowState.Detached) - return false; - return _current >= 0; - case DataRowVersion.Original: - if (rowState == DataRowState.Detached) - return false; - return _original >= 0; - } + switch (version) { + case DataRowVersion.Default: + if (rowState == DataRowState.Deleted && !_inExpressionEvaluation) + return false; + if (rowState == DataRowState.Detached) + return _proposed >= 0; + return true; + case DataRowVersion.Proposed: + if (rowState == DataRowState.Deleted && !_inExpressionEvaluation) + return false; + return _proposed >= 0; + case DataRowVersion.Current: + if ((rowState == DataRowState.Deleted && !_inExpressionEvaluation) || rowState == DataRowState.Detached) + return false; + return _current >= 0; + case DataRowVersion.Original: + if (rowState == DataRowState.Detached) + return false; + return _original >= 0; + } return false; } @@ -1276,7 +1368,7 @@ namespace System.Data { /// public void SetParentRow (DataRow parentRow, DataRelation relation) { - if (_table == null || parentRow.Table == null || RowState == DataRowState.Detached) + if (_table == null || parentRow.Table == null) throw new RowNotInTableException("This row has been removed from a table and does not have any data. BeginEdit() will allow creation of new data in this row."); if (parentRow != null && _table.DataSet != parentRow.Table.DataSet) @@ -1287,8 +1379,8 @@ namespace System.Data { { foreach (DataRelation parentRel in _table.ParentRelations) { - DataColumn[] childCols = parentRel.ChildKeyConstraint.Columns; - DataColumn[] parentCols = parentRel.ChildKeyConstraint.RelatedColumns; + DataColumn[] childCols = parentRel.ChildColumns; + DataColumn[] parentCols = parentRel.ParentColumns; for (int i = 0; i < parentCols.Length; i++) { @@ -1302,8 +1394,8 @@ namespace System.Data { } else { - DataColumn[] childCols = relation.ChildKeyConstraint.Columns; - DataColumn[] parentCols = relation.ChildKeyConstraint.RelatedColumns; + DataColumn[] childCols = relation.ChildColumns; + DataColumn[] parentCols = relation.ParentColumns; for (int i = 0; i < parentCols.Length; i++) { @@ -1355,8 +1447,8 @@ namespace System.Data { } //Saving the current value as the column value - row[index] = targetColumn[row._current]; - + object defaultVal = column [IndexFromVersion (DataRowVersion.Default)]; + row [index] = defaultVal; } } CopyState(row); @@ -1432,6 +1524,71 @@ namespace System.Data { } #endregion // Methods + +#if NET_2_0 + /// + /// This method loads a given value into the existing row affecting versions, + /// state based on the LoadOption. The matrix of changes for this method are as + /// mentioned in the DataTable.Load (IDataReader, LoadOption) method. + /// + [MonoTODO ("Raise necessary Events")] + internal void Load (object [] values, LoadOption loadOption, bool is_new) + { + DataRowAction action = DataRowAction.Change; + + int temp = Table.RecordCache.NewRecord (); + for (int i = 0 ; i < Table.Columns.Count; i++) + SetValue (i, values [i], temp); + + if (is_new) { // new row + if (editing || RowState == DataRowState.Detached) + Proposed = temp; + else + Current = temp; + return; + } + + if (loadOption == LoadOption.OverwriteChanges + || (loadOption == LoadOption.PreserveChanges + && rowState == DataRowState.Unchanged)) { + Original = temp; + if (editing) + Proposed = temp; + else + Current = temp; + rowState = DataRowState.Unchanged; + action = DataRowAction.ChangeCurrentAndOriginal; + return; + } + + if (loadOption == LoadOption.PreserveChanges) { + if (rowState != DataRowState.Deleted) { + Original = temp; + rowState = DataRowState.Modified; + action = DataRowAction.ChangeOriginal; + } + return; + } + + bool not_used = true; + // Upsert + if (rowState != DataRowState.Deleted) { + int index = editing ? _proposed : _current; + if (! RecordCache.CompareRecords (Table, index, temp)) { + if (editing) + Proposed = temp; + else + Current = temp; + not_used = false; + if (rowState == DataRowState.Unchanged) + rowState = DataRowState.Modified; + } + } + + if (not_used) + Table.RecordCache.DisposeRecord (temp); + } +#endif // NET_2_0 }