using System.Collections;
using System.Globalization;
using System.Xml;
+#if NET_2_0
+using System.ComponentModel;
+#endif
namespace System.Data {
/// <summary>
/// Represents a row of data in a DataTable.
/// </summary>
+#if !NET_2_0
[Serializable]
+#endif
public class DataRow
{
#region Fields
}
CheckValue (value, column);
-
bool orginalEditing = Proposed >= 0;
if (!orginalEditing) {
BeginEdit ();
get {
if (columnIndex < 0 || columnIndex > _table.Columns.Count)
throw new IndexOutOfRangeException ();
- // Accessing deleted rows
- if (!_inExpressionEvaluation && RowState == DataRowState.Deleted && version != DataRowVersion.Original)
- throw new DeletedRowInaccessibleException ("Deleted row information cannot be accessed through the row.");
DataColumn column = _table.Columns[columnIndex];
int recordIndex = IndexFromVersion(version);
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.");
-
return column[recordIndex];
}
}
/// </summary>
public object[] ItemArray {
get {
- // row not in table
- if (RowState == DataRowState.Detached)
- 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.");
// Accessing deleted rows
if (RowState == DataRowState.Deleted)
throw new DeletedRowInaccessibleException ("Deleted row information cannot be accessed through the row.");
+
+ int index = 0;
+ if (RowState == DataRowState.Detached)
+ // Check if datarow is removed from the table.
+ if (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.");
+ else
+ index = Proposed;
+ else
+ index = Current;
object[] items = new object[_table.Columns.Count];
- foreach(DataColumn column in _table.Columns) {
- items[column.Ordinal] = column[Current];
- }
+
+ foreach(DataColumn column in _table.Columns)
+ items[column.Ordinal] = column[index];
return items;
}
set {
public DataRowState RowState {
get {
//return rowState;
- if ((Original == -1) && (Current == -1))
- {
- return DataRowState.Detached;
- }
- if (Original == Current)
- {
- return DataRowState.Unchanged;
- }
- if (Original == -1)
- {
- return DataRowState.Added;
- }
- if (Current == -1)
- {
- return DataRowState.Deleted;
- }
- return DataRowState.Modified;
+ if ((Original == -1) && (Current == -1))
+ return DataRowState.Detached;
+ if (Original == Current)
+ return DataRowState.Unchanged;
+ if (Original == -1)
+ return DataRowState.Added;
+ if (Current == -1)
+ return DataRowState.Deleted;
+ return DataRowState.Modified;
}
}
return;
case DataRowState.Added:
case DataRowState.Modified:
+ int original = Original;
+ DataRowState oldState = RowState;
if (Original >= 0) {
Table.RecordCache.DisposeRecord(Original);
}
Original = Current;
+ foreach (Index index in Table.Indexes)
+ index.Update(this, original, DataRowVersion.Original, oldState);
break;
case DataRowState.Deleted:
+ Table.DeleteRowFromIndexes(this);
_table.Rows.RemoveInternal (this);
DetachRow();
break;
/// <summary>
/// Begins an edit operation on a DataRow object.
/// </summary>
+#if NET_2_0
+ [EditorBrowsable (EditorBrowsableState.Advanced)]
+#endif
public void BeginEdit ()
{
if (_inChangingEvent)
/// <summary>
/// Cancels the current edit on the row.
/// </summary>
+#if NET_2_0
+ [EditorBrowsable (EditorBrowsableState.Advanced)]
+#endif
public void CancelEdit ()
{
if (_inChangingEvent) {
}
if (HasVersion (DataRowVersion.Proposed)) {
+ int oldRecord = Proposed;
+ DataRowState oldState = RowState;
Table.RecordCache.DisposeRecord(Proposed);
Proposed = -1;
+
+ foreach(Index index in Table.Indexes)
+ index.Update(this,oldRecord, DataRowVersion.Proposed, oldState);
}
}
default:
// check what to do with child rows
CheckChildRows(DataRowAction.Delete);
- _table.DeleteRowFromIndexes (this);
break;
}
if (Current >= 0) {
+ int current = Current;
+ DataRowState oldState = RowState;
if (Current != Original) {
_table.RecordCache.DisposeRecord(Current);
}
Current = -1;
+ foreach(Index index in Table.Indexes)
+ index.Update(this, current, DataRowVersion.Current, oldState);
}
_table.DeletedDataRow(this, DataRowAction.Delete);
}
case DataRowAction.Rollback: {
if (childRows[j].RowState != DataRowState.Unchanged)
childRows[j].RejectChanges ();
-
break;
}
}
/// <summary>
/// Ends the edit occurring on the row.
/// </summary>
+#if NET_2_0
+ [EditorBrowsable (EditorBrowsableState.Advanced)]
+#endif
public void EndEdit ()
{
if (_inChangingEvent)
_inChangingEvent = false;
}
- //Calling next method validates UniqueConstraints
- //and ForeignKeys.
- bool rowValidated = false;
- try
- {
- if ((_table.DataSet == null || _table.DataSet.EnforceConstraints) && !_table._duringDataLoad) {
- _table.Rows.ValidateDataRowInternal(this);
- rowValidated = true;
- }
- }
- catch (Exception e)
- {
- Table.RecordCache.DisposeRecord(Proposed);
- Proposed = -1;
- throw e;
- }
-
- CheckChildRows(DataRowAction.Change);
- if (Original != Current) {
- Table.RecordCache.DisposeRecord(Current);
- }
+ DataRowState oldState = RowState;
+ int oldRecord = Current;
Current = Proposed;
Proposed = -1;
- if (!rowValidated) {
- // keep indexes updated even if there was no need to validate row
+ if (!Table._duringDataLoad) {
foreach(Index index in Table.Indexes) {
- index.Update(this,Current); //FIXME: why Current ?!
+ index.Update(this,oldRecord, DataRowVersion.Current, oldState);
}
}
+ try {
+ AssertConstraints();
+
+ // restore previous state to let the cascade update to find the rows
+ Proposed = Current;
+ Current = oldRecord;
+
+ CheckChildRows(DataRowAction.Change);
+
+ // apply new state
+ Current = Proposed;
+ Proposed = -1;
+ }
+ catch {
+ int proposed = Proposed >= 0 ? Proposed : Current;
+ Current = oldRecord;
+ if (!Table._duringDataLoad) {
+ foreach(Index index in Table.Indexes) {
+ index.Update(this,proposed, DataRowVersion.Current, RowState);
+ }
+ }
+ throw;
+ }
+
+ if (Original != oldRecord) {
+ Table.RecordCache.DisposeRecord(oldRecord);
+ }
+
// Note : row state must not be changed before all the job on indexes finished,
// since the indexes works with recods rather than with rows and the decision
// which of row records to choose depends on row state.
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 original is null, then nothing has happened since AcceptChanges
// was last called. We have no "original" to go back to.
- if (HasVersion(DataRowVersion.Original)) {
- if (Current >= 0 && Current != Original) {
- Table.RecordCache.DisposeRecord(Current);
- }
- CheckChildRows(DataRowAction.Rollback);
+
+ _table.ChangedDataRow (this, DataRowAction.Rollback);
+ CancelEdit ();
+ //TODO : Need to Verify the constraints..
+ switch (RowState) {
+ case DataRowState.Added:
+ _table.DeleteRowFromIndexes (this);
+ _table.Rows.RemoveInternal (this);
+ DetachRow ();
+ break;
+ case DataRowState.Modified:
+ Table.RecordCache.DisposeRecord (Current);
+ CheckChildRows (DataRowAction.Rollback);
+ Table.DeleteRowFromIndexes(this);
Current = Original;
-
- _table.ChangedDataRow (this, DataRowAction.Rollback);
- CancelEdit ();
- switch (RowState)
- {
- case DataRowState.Added:
- _table.DeleteRowFromIndexes (this);
- _table.Rows.RemoveInternal (this);
- break;
- case DataRowState.Modified:
- if ((_table.DataSet == null || _table.DataSet.EnforceConstraints) && !_table._duringDataLoad)
- _table.Rows.ValidateDataRowInternal(this);
- break;
- case DataRowState.Deleted:
- if ((_table.DataSet == null || _table.DataSet.EnforceConstraints) && !_table._duringDataLoad)
- _table.Rows.ValidateDataRowInternal(this);
- break;
- }
-
- }
- else {
- // If rows are just loaded via Xml the original values are null.
- // So in this case we have to remove all columns.
- // FIXME: I'm not realy sure, does this break something else, but
- // if so: FIXME ;)
-
- if ((RowState & DataRowState.Added) > 0)
- {
- _table.DeleteRowFromIndexes (this);
- _table.Rows.RemoveInternal (this);
- // if row was in Added state we move it to Detached.
- DetachRow();
- }
+ break;
+ case DataRowState.Deleted:
+ CheckChildRows (DataRowAction.Rollback);
+ Table.DeleteRowFromIndexes(this);
+ Current = Original;
+ break;
}
}
}
}
+ internal void Validate() {
+ Table.AddRowToIndexes(this);
+ AssertConstraints();
+ }
+
+ void AssertConstraints() {
+ if (Table == null || Table._duringDataLoad)
+ return;
+
+ if (Table.DataSet != null && !Table.DataSet.EnforceConstraints)
+ return;
+ foreach(DataColumn column in Table.Columns) {
+ if (!column.AllowDBNull && IsNull(column)) {
+ throw new NoNullAllowedException(_nullConstraintMessage);
+ }
+ }
+
+ foreach(Constraint constraint in Table.Constraints) {
+ try {
+ constraint.AssertConstraint(this);
+ }
+ catch(Exception e) {
+ Table.DeleteRowFromIndexes(this);
+ throw e;
+ }
+ }
+ }
+
internal void CheckNullConstraints()
{
if (_nullConstraintViolation) {
&& RowState == DataRowState.Unchanged)) {
Table.ChangingDataRow (this, DataRowAction.ChangeCurrentAndOriginal);
temp = Table.CreateRecord (values);
+ Table.DeleteRowFromIndexes(this);
if (HasVersion (DataRowVersion.Original) && Current != Original)
Table.RecordCache.DisposeRecord (Original);
Original = temp;
- // update the pk index
- index = Table.GetIndex(Table.PrimaryKey,null,DataViewRowState.None,null,false);
- if (index != null)
- index.Update (this, temp);
if (HasVersion (DataRowVersion.Current))
Table.RecordCache.DisposeRecord (Current);
Current = temp;
+ Table.AddRowToIndexes(this);
Table.ChangedDataRow (this, DataRowAction.ChangeCurrentAndOriginal);
return;
}
if (RowState == DataRowState.Added
|| Table.CompareRecords (rindex, temp) != 0) {
Table.ChangingDataRow (this, DataRowAction.Change);
+ Table.DeleteRowFromIndexes(this);
if (HasVersion (DataRowVersion.Proposed)) {
Table.RecordCache.DisposeRecord (Proposed);
Proposed = -1;
}
-
- // update the pk index
- index = Table.GetIndex(Table.PrimaryKey,null,DataViewRowState.None,null,false);
- if (index != null)
- index.Update (this, temp);
-
+
if (Original != Current)
Table.RecordCache.DisposeRecord (Current);
Current = temp;
+ Table.AddRowToIndexes(this);
Table.ChangedDataRow (this, DataRowAction.Change);
} else {
Table.ChangingDataRow (this, DataRowAction.Nothing);