-//\r
-// System.Data.DataRow.cs\r
-//\r
-// Author:\r
-// Rodrigo Moya <rodrigo@ximian.com>\r
-// Daniel Morgan <danmorg@sc.rr.com>\r
-// Tim Coleman <tim@timcoleman.com>\r
-// Ville Palo <vi64pa@koti.soon.fi>\r
-// Alan Tam Siu Lung <Tam@SiuLung.com>\r
-//\r
-// (C) Ximian, Inc 2002\r
-// (C) Daniel Morgan 2002, 2003\r
-// Copyright (C) 2002 Tim Coleman\r
-//\r
-\r
-using System;\r
-using System.Collections;\r
-using System.Globalization;\r
-\r
-namespace System.Data {\r
- /// <summary>\r
- /// Represents a row of data in a DataTable.\r
- /// </summary>\r
- [Serializable]\r
- public class DataRow\r
- {\r
- #region Fields\r
-\r
- private DataTable _table;\r
-\r
- private object[] original;\r
- private object[] proposed;\r
- private object[] current;\r
-\r
- private string[] columnErrors;\r
- private string rowError;\r
- private DataRowState rowState;\r
- internal int xmlRowID = 0;\r
- internal bool _nullConstraintViolation;\r
- private bool editing = false;\r
- private bool _hasParentCollection;\r
-\r
- #endregion\r
-\r
- #region Constructors\r
-\r
- /// <summary>\r
- /// This member supports the .NET Framework infrastructure and is not intended to be \r
- /// used directly from your code.\r
- /// </summary>\r
- protected internal DataRow (DataRowBuilder builder)\r
- {\r
- _table = builder.Table;\r
-\r
- original = null; \r
- \r
- proposed = new object[_table.Columns.Count];\r
- for (int c = 0; c < _table.Columns.Count; c++) \r
- {\r
- proposed[c] = DBNull.Value;\r
- }\r
- \r
- columnErrors = new string[_table.Columns.Count];\r
- rowError = String.Empty;\r
-\r
- //on first creating a DataRow it is always detached.\r
- rowState = DataRowState.Detached;\r
- \r
- foreach (DataColumn Col in _table.Columns) {\r
- \r
- if (Col.AutoIncrement) {\r
- this [Col] = Col.AutoIncrementValue();\r
- }\r
- }\r
- _table.Columns.CollectionChanged += new System.ComponentModel.CollectionChangeEventHandler(CollectionChanged);\r
- }\r
-\r
- \r
- #endregion\r
-\r
- #region Properties\r
-\r
- /// <summary>\r
- /// Gets a value indicating whether there are errors in a row.\r
- /// </summary>\r
- public bool HasErrors {\r
- [MonoTODO]\r
- get {\r
- if (RowError != string.Empty)\r
- return true;\r
-\r
- for (int i= 0; i < columnErrors.Length; i++){\r
- if (columnErrors[i] != null && columnErrors[i] != string.Empty)\r
- return true;\r
- }\r
-\r
- return false;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Gets or sets the data stored in the column specified by name.\r
- /// </summary>\r
- public object this[string columnName] {\r
- get { return this[columnName, DataRowVersion.Default]; }\r
- set {\r
- int columnIndex = _table.Columns.IndexOf (columnName);\r
- if (columnIndex == -1)\r
- throw new IndexOutOfRangeException ();\r
- this[columnIndex] = value;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Gets or sets the data stored in specified DataColumn\r
- /// </summary>\r
- public object this[DataColumn column] {\r
-\r
- get {\r
- return this[column, DataRowVersion.Default];} \r
- set {\r
- int columnIndex = _table.Columns.IndexOf (column);\r
- if (columnIndex == -1)\r
- throw new ArgumentException ("The column does not belong to this table.");\r
- this[columnIndex] = value;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Gets or sets the data stored in column specified by index.\r
- /// </summary>\r
- public object this[int columnIndex] {\r
- get { return this[columnIndex, DataRowVersion.Default]; }\r
- set {\r
- if (columnIndex < 0 || columnIndex > _table.Columns.Count)\r
- throw new IndexOutOfRangeException ();\r
- if (rowState == DataRowState.Deleted)\r
- throw new DeletedRowInaccessibleException ();\r
- DataColumn column = _table.Columns[columnIndex];\r
- _table.ChangingDataColumn (this, column, value);\r
- \r
- \r
- bool orginalEditing = editing;\r
- if (!orginalEditing) BeginEdit ();\r
- object v = SetColumnValue (value, columnIndex);\r
- proposed[columnIndex] = v;\r
- _table.ChangedDataColumn (this, column, v);\r
- if (!orginalEditing) EndEdit ();\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Gets the specified version of data stored in the named column.\r
- /// </summary>\r
- public object this[string columnName, DataRowVersion version] {\r
- get {\r
- int columnIndex = _table.Columns.IndexOf (columnName);\r
- if (columnIndex == -1)\r
- throw new IndexOutOfRangeException ();\r
- return this[columnIndex, version];\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Gets the specified version of data stored in the specified DataColumn.\r
- /// </summary>\r
- public object this[DataColumn column, DataRowVersion version] {\r
- get {\r
- int columnIndex = _table.Columns.IndexOf (column);\r
- if (columnIndex == -1)\r
- throw new ArgumentException ("The column does not belong to this table.");\r
- return this[columnIndex, version];\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Gets the data stored in the column, specified by index and version of the data to\r
- /// retrieve.\r
- /// </summary>\r
- public object this[int columnIndex, DataRowVersion version] {\r
- get {\r
- if (columnIndex < 0 || columnIndex > _table.Columns.Count)\r
- throw new IndexOutOfRangeException ();\r
- // Non-existent version\r
- if (rowState == DataRowState.Detached && version == DataRowVersion.Current || !HasVersion (version))\r
- throw new VersionNotFoundException (Locale.GetText ("There is no " + version.ToString () + " data to access."));\r
+//
+// System.Data.DataRow.cs
+//
+// Author:
+// Rodrigo Moya <rodrigo@ximian.com>
+// Daniel Morgan <danmorg@sc.rr.com>
+// Tim Coleman <tim@timcoleman.com>
+// Ville Palo <vi64pa@koti.soon.fi>
+// Alan Tam Siu Lung <Tam@SiuLung.com>
+//
+// (C) Ximian, Inc 2002
+// (C) Daniel Morgan 2002, 2003
+// Copyright (C) 2002 Tim Coleman
+//
+
+using System;
+using System.Collections;
+using System.Globalization;
+
+namespace System.Data {
+ /// <summary>
+ /// Represents a row of data in a DataTable.
+ /// </summary>
+ [Serializable]
+ public class DataRow
+ {
+ #region Fields
+
+ private DataTable _table;
+
+ private object[] original;
+ private object[] proposed;
+ private object[] current;
+
+ private string[] columnErrors;
+ private string rowError;
+ private DataRowState rowState;
+ internal int xmlRowID = 0;
+ internal bool _nullConstraintViolation;
+ private string _nullConstraintMessage;
+ private bool editing = false;
+ private bool _hasParentCollection;
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// This member supports the .NET Framework infrastructure and is not intended to be
+ /// used directly from your code.
+ /// </summary>
+ protected internal DataRow (DataRowBuilder builder)
+ {
+ _table = builder.Table;
+
+ original = null;
+
+ proposed = new object[_table.Columns.Count];
+ for (int c = 0; c < _table.Columns.Count; c++)
+ {
+ proposed[c] = DBNull.Value;
+ }
+
+ columnErrors = new string[_table.Columns.Count];
+ rowError = String.Empty;
+
+ //on first creating a DataRow it is always detached.
+ rowState = DataRowState.Detached;
+
+ foreach (DataColumn Col in _table.Columns) {
+
+ if (Col.AutoIncrement) {
+ this [Col] = Col.AutoIncrementValue();
+ }
+ }
+ _table.Columns.CollectionChanged += new System.ComponentModel.CollectionChangeEventHandler(CollectionChanged);
+ }
+
+
+ #endregion
+
+ #region Properties
+
+ /// <summary>
+ /// Gets a value indicating whether there are errors in a row.
+ /// </summary>
+ public bool HasErrors {
+ [MonoTODO]
+ get {
+ if (RowError != string.Empty)
+ return true;
+
+ for (int i= 0; i < columnErrors.Length; i++){
+ if (columnErrors[i] != null && columnErrors[i] != string.Empty)
+ return true;
+ }
+
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the data stored in the column specified by name.
+ /// </summary>
+ public object this[string columnName] {
+ get { return this[columnName, DataRowVersion.Default]; }
+ set {
+ int columnIndex = _table.Columns.IndexOf (columnName);
+ if (columnIndex == -1)
+ throw new IndexOutOfRangeException ();
+ this[columnIndex] = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the data stored in specified DataColumn
+ /// </summary>
+ public object this[DataColumn column] {
+
+ get {
+ return this[column, DataRowVersion.Default];}
+ set {
+ int columnIndex = _table.Columns.IndexOf (column);
+ if (columnIndex == -1)
+ throw new ArgumentException ("The column does not belong to this table.");
+ this[columnIndex] = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the data stored in column specified by index.
+ /// </summary>
+ public object this[int columnIndex] {
+ get { return this[columnIndex, DataRowVersion.Default]; }
+ set {
+ if (columnIndex < 0 || columnIndex > _table.Columns.Count)
+ throw new IndexOutOfRangeException ();
+ if (rowState == DataRowState.Deleted)
+ throw new DeletedRowInaccessibleException ();
+ DataColumn column = _table.Columns[columnIndex];
+ _table.ChangingDataColumn (this, column, value);
+
+
+ bool orginalEditing = editing;
+ if (!orginalEditing) BeginEdit ();
+ object v = SetColumnValue (value, columnIndex);
+ proposed[columnIndex] = v;
+ _table.ChangedDataColumn (this, column, v);
+ if (!orginalEditing) EndEdit ();
+ }
+ }
+
+ /// <summary>
+ /// Gets the specified version of data stored in the named column.
+ /// </summary>
+ public object this[string columnName, DataRowVersion version] {
+ get {
+ int columnIndex = _table.Columns.IndexOf (columnName);
+ if (columnIndex == -1)
+ throw new IndexOutOfRangeException ();
+ return this[columnIndex, version];
+ }
+ }
+
+ /// <summary>
+ /// Gets the specified version of data stored in the specified DataColumn.
+ /// </summary>
+ public object this[DataColumn column, DataRowVersion version] {
+ get {
+ int columnIndex = _table.Columns.IndexOf (column);
+ if (columnIndex == -1)
+ throw new ArgumentException ("The column does not belong to this table.");
+ return this[columnIndex, version];
+ }
+ }
+
+ /// <summary>
+ /// Gets the data stored in the column, specified by index and version of the data to
+ /// retrieve.
+ /// </summary>
+ public object this[int columnIndex, DataRowVersion version] {
+ get {
+ if (columnIndex < 0 || columnIndex > _table.Columns.Count)
+ throw new IndexOutOfRangeException ();
+ // Accessing deleted rows
+ if (rowState == DataRowState.Deleted && version != DataRowVersion.Original)
+ throw new DeletedRowInaccessibleException ("Deleted row information cannot be accessed through the row.");
+ // Non-existent version
+ if (rowState == DataRowState.Detached && version == DataRowVersion.Current || !HasVersion (version))
+ throw new VersionNotFoundException (Locale.GetText ("There is no " + version.ToString () + " data to access."));
+ switch (version) {
+ case DataRowVersion.Default:
+ if (editing || rowState == DataRowState.Detached)
+ return proposed[columnIndex];
+ return current[columnIndex];
+ case DataRowVersion.Proposed:
+ return proposed[columnIndex];
+ case DataRowVersion.Current:
+ return current[columnIndex];
+ case DataRowVersion.Original:
+ return original[columnIndex];
+ default:
+ throw new ArgumentException ();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets all of the values for this row through an array.
+ /// </summary>
+ [MonoTODO]
+ public object[] ItemArray {
+ get {
// Accessing deleted rows\r
- if (rowState == DataRowState.Deleted && version != DataRowVersion.Original)\r
- throw new DeletedRowInaccessibleException ("Deleted row information cannot be accessed through the row.");\r
- switch (version) {\r
- case DataRowVersion.Default:\r
- if (editing || rowState == DataRowState.Detached)\r
- return proposed[columnIndex];\r
- return current[columnIndex];\r
- case DataRowVersion.Proposed:\r
- return proposed[columnIndex];\r
- case DataRowVersion.Current:\r
- return current[columnIndex];\r
- case DataRowVersion.Original:\r
- return original[columnIndex];\r
- default:\r
- throw new ArgumentException ();\r
- }\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Gets or sets all of the values for this row through an array.\r
- /// </summary>\r
- [MonoTODO]\r
- public object[] ItemArray {\r
- get { \r
- return current; \r
- }\r
- set {\r
- if (value.Length > _table.Columns.Count)\r
- throw new ArgumentException ();\r
-\r
if (rowState == DataRowState.Deleted)\r
- throw new DeletedRowInaccessibleException ();\r
- \r
- object[] newItems = new object[_table.Columns.Count]; \r
- object v = null;\r
- for (int i = 0; i < _table.Columns.Count; i++) {\r
-\r
- if (i < value.Length)\r
- v = value[i];\r
- else\r
- v = null;\r
-\r
- newItems[i] = SetColumnValue (v, i);\r
- }\r
-\r
- bool orginalEditing = editing;\r
- if (!orginalEditing) BeginEdit ();\r
- proposed = newItems;\r
- if (!orginalEditing) EndEdit ();\r
- }\r
- }\r
-\r
+ throw new DeletedRowInaccessibleException ("Deleted row information cannot be accessed through the row.");\r
+
+ return current;
+ }
+ set {
+ if (value.Length > _table.Columns.Count)
+ throw new ArgumentException ();
+
+ if (rowState == DataRowState.Deleted)
+ throw new DeletedRowInaccessibleException ();
+
+ object[] newItems = new object[_table.Columns.Count];
+ object v = null;
+ for (int i = 0; i < _table.Columns.Count; i++) {
+
+ if (i < value.Length)
+ v = value[i];
+ else
+ v = null;
+
+ newItems[i] = SetColumnValue (v, i);
+ }
+
+ bool orginalEditing = editing;
+ if (!orginalEditing) BeginEdit ();
+ proposed = newItems;
+ if (!orginalEditing) EndEdit ();
+ }
+ }
+
private object SetColumnValue (object v, int index) \r
{ \r
object newval = null;\r
{\r
if (!col.AllowDBNull)\r
{\r
- if (!this._table._duringDataLoad)\r
- {\r
- throw new NoNullAllowedException ();\r
- }\r
- else \r
- {\r
- //Constraint violations during data load is raise in DataTable EndLoad\r
- this._nullConstraintViolation = true;\r
- \r
- }\r
+ //Constraint violations during data load is raise in DataTable EndLoad\r
+ this._nullConstraintViolation = true;\r
+ _nullConstraintMessage = "Column '" + col.ColumnName + "' does not allow nulls.";\r
}\r
\r
- newval= DBNull.Value;\r
- \r
- \r
+ newval = DBNull.Value;\r
}\r
} \r
else if (v == DBNull.Value) \r
\r
if (!col.AllowDBNull)\r
{\r
- if (!this._table._duringDataLoad)\r
- {\r
- throw new NoNullAllowedException ();\r
- }\r
- else \r
- {\r
- //Constraint violations during data load is raise in DataTable EndLoad\r
- this._nullConstraintViolation = true;\r
- \r
- }\r
+ //Constraint violations during data load is raise in DataTable EndLoad\r
+ this._nullConstraintViolation = true;\r
+ _nullConstraintMessage = "Column '" + col.ColumnName + "' does not allow nulls.";\r
}\r
- newval= DBNull.Value;\r
+ \r
+ newval = DBNull.Value;\r
}\r
else \r
{ \r
{\r
TypeCode typeCode = Type.GetTypeCode(cType);\r
switch(typeCode) {\r
- case TypeCode.Boolean :\r
- v = Convert.ToBoolean (v);\r
- break;\r
- case TypeCode.Byte :\r
- v = Convert.ToByte (v);\r
- break;\r
- case TypeCode.Char :\r
- v = Convert.ToChar (v);\r
- break;\r
- case TypeCode.DateTime :\r
- v = Convert.ToDateTime (v);\r
- break;\r
- case TypeCode.Decimal :\r
- v = Convert.ToDecimal (v);\r
- break;\r
- case TypeCode.Double :\r
- v = Convert.ToDouble (v);\r
- break;\r
- case TypeCode.Int16 :\r
- v = Convert.ToInt16 (v);\r
- break;\r
- case TypeCode.Int32 :\r
- v = Convert.ToInt32 (v);\r
- break;\r
- case TypeCode.Int64 :\r
- v = Convert.ToInt64 (v);\r
- break;\r
- case TypeCode.SByte :\r
- v = Convert.ToSByte (v);\r
- break;\r
- case TypeCode.Single :\r
- v = Convert.ToSingle (v);\r
- break;\r
- case TypeCode.String :\r
- v = Convert.ToString (v);\r
- break;\r
- case TypeCode.UInt16 :\r
- v = Convert.ToUInt16 (v);\r
- break;\r
- case TypeCode.UInt32 :\r
- v = Convert.ToUInt32 (v);\r
- break;\r
- case TypeCode.UInt64 :\r
- v = Convert.ToUInt64 (v);\r
- break;\r
- default :\r
- switch(cType.ToString()) {\r
- case "System.TimeSpan" :\r
- v = (System.TimeSpan) v;\r
+ case TypeCode.Boolean :\r
+ v = Convert.ToBoolean (v);\r
+ break;\r
+ case TypeCode.Byte :\r
+ v = Convert.ToByte (v);\r
+ break;\r
+ case TypeCode.Char :\r
+ v = Convert.ToChar (v);\r
+ break;\r
+ case TypeCode.DateTime :\r
+ v = Convert.ToDateTime (v);\r
+ break;\r
+ case TypeCode.Decimal :\r
+ v = Convert.ToDecimal (v);\r
+ break;\r
+ case TypeCode.Double :\r
+ v = Convert.ToDouble (v);\r
+ break;\r
+ case TypeCode.Int16 :\r
+ v = Convert.ToInt16 (v);\r
+ break;\r
+ case TypeCode.Int32 :\r
+ v = Convert.ToInt32 (v);\r
break;\r
- case "System.Type" :\r
- v = (System.Type) v;\r
+ case TypeCode.Int64 :\r
+ v = Convert.ToInt64 (v);\r
break;\r
- case "System.Object" :\r
- //v = (System.Object) v;\r
+ case TypeCode.SByte :\r
+ v = Convert.ToSByte (v);\r
+ break;\r
+ case TypeCode.Single :\r
+ v = Convert.ToSingle (v);\r
+ break;\r
+ case TypeCode.String :\r
+ v = Convert.ToString (v);\r
+ break;\r
+ case TypeCode.UInt16 :\r
+ v = Convert.ToUInt16 (v);\r
+ break;\r
+ case TypeCode.UInt32 :\r
+ v = Convert.ToUInt32 (v);\r
+ break;\r
+ case TypeCode.UInt64 :\r
+ v = Convert.ToUInt64 (v);\r
+ break;\r
+ default :\r
+ \r
+ switch(cType.ToString()) {\r
+ case "System.TimeSpan" :\r
+ v = (System.TimeSpan) v;\r
+ break;\r
+ case "System.Type" :\r
+ v = (System.Type) v;\r
+ break;\r
+ case "System.Object" :\r
+ //v = (System.Object) v;\r
+ break;\r
+ default:\r
+ if (!cType.IsArray)\r
+ throw new InvalidCastException("Type not supported.");\r
+ break;\r
+ }\r
break;\r
- default:\r
- // FIXME: is exception correct?\r
- throw new InvalidCastException("Type not supported.");\r
}\r
- break;\r
- }\r
- vType = v.GetType();\r
+ vType = v.GetType();\r
}\r
newval = v;\r
if(col.AutoIncrement == true) {\r
col.DataHasBeenSet = true;\r
return newval;\r
}\r
-\r
- /// <summary>\r
- /// Gets or sets the custom error description for a row.\r
- /// </summary>\r
- public string RowError {\r
- get { return rowError; }\r
- set { rowError = value; }\r
- }\r
-\r
- /// <summary>\r
- /// Gets the current state of the row in regards to its relationship to the\r
- /// DataRowCollection.\r
- /// </summary>\r
- public DataRowState RowState {\r
- get { return rowState; }\r
- }\r
-\r
- //FIXME?: Couldn't find a way to set the RowState when adding the DataRow\r
- //to a Datatable so I added this method. Delete if there is a better way.\r
- internal void AttachRow() {\r
- current = proposed;\r
- proposed = null;\r
- rowState = DataRowState.Added;\r
- }\r
-\r
- //FIXME?: Couldn't find a way to set the RowState when removing the DataRow\r
- //from a Datatable so I added this method. Delete if there is a better way.\r
- internal void DetachRow() {\r
- proposed = null;\r
- _hasParentCollection = false;\r
- rowState = DataRowState.Detached;\r
- }\r
-\r
- /// <summary>\r
- /// Gets the DataTable for which this row has a schema.\r
- /// </summary>\r
- public DataTable Table {\r
- get { return _table; }\r
- }\r
-\r
- /// <summary>\r
- /// Gets and sets index of row. This is used from \r
- /// XmlDataDocument.\r
- // </summary>\r
- internal int XmlRowID {\r
- get { return xmlRowID; }\r
- set { xmlRowID = value; }\r
- }\r
-\r
- #endregion\r
-\r
- #region Methods\r
-\r
- /// <summary>\r
- /// Commits all the changes made to this row since the last time AcceptChanges was\r
- /// called.\r
- /// </summary>\r
- public void AcceptChanges () \r
- {\r
- EndEdit(); // in case it hasn't been called\r
- switch (rowState) {\r
- case DataRowState.Added:\r
- case DataRowState.Modified:\r
- rowState = DataRowState.Unchanged;\r
- break;\r
- case DataRowState.Deleted:\r
- _table.Rows.Remove (this);\r
- break;\r
- case DataRowState.Detached:\r
- throw new RowNotInTableException("Cannot perform this operation on a row not in the table.");\r
- }\r
- // Accept from detached\r
- if (original == null)\r
- original = new object[_table.Columns.Count];\r
- Array.Copy (current, original, _table.Columns.Count);\r
- }\r
-\r
- /// <summary>\r
- /// Begins an edit operation on a DataRow object.\r
- /// </summary>\r
- [MonoTODO]\r
- public void BeginEdit () \r
- {\r
- if (rowState == DataRowState.Deleted)\r
- throw new DeletedRowInaccessibleException ();\r
- if (!HasVersion (DataRowVersion.Proposed)) {\r
- proposed = new object[_table.Columns.Count];\r
- Array.Copy (current, proposed, current.Length);\r
- }\r
- //TODO: Suspend validation\r
- editing = true;\r
- }\r
-\r
- /// <summary>\r
- /// Cancels the current edit on the row.\r
- /// </summary>\r
- [MonoTODO]\r
- public void CancelEdit () \r
- {\r
- editing = false;\r
- //TODO: Events\r
- if (HasVersion (DataRowVersion.Proposed)) {\r
- proposed = null;\r
- if (rowState == DataRowState.Modified)\r
- rowState = DataRowState.Unchanged;\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Clears the errors for the row, including the RowError and errors set with\r
- /// SetColumnError.\r
- /// </summary>\r
- public void ClearErrors () \r
- {\r
- rowError = String.Empty;\r
- columnErrors = new String[_table.Columns.Count];\r
- }\r
-\r
- /// <summary>\r
- /// Deletes the DataRow.\r
- /// </summary>\r
- [MonoTODO]\r
- public void Delete () \r
- {\r
- switch (rowState) {\r
- case DataRowState.Added:\r
- Table.Rows.Remove (this);\r
- break;\r
- case DataRowState.Deleted:\r
- throw new DeletedRowInaccessibleException ();\r
- default:\r
- _table.DeletingDataRow(this, DataRowAction.Delete);\r
- // check what to do with child rows\r
- CheckChildRows(DataRowAction.Delete);\r
- rowState = DataRowState.Deleted;\r
- _table.DeletedDataRow(this, DataRowAction.Delete);\r
- break;\r
- }\r
- }\r
-\r
- // check the child rows of this row before deleting the row.\r
- private void CheckChildRows(DataRowAction action)\r
- {\r
- \r
- // in this method we find the row that this row is in a reltion with them.\r
- // in shortly we find all child rows of this row.\r
- // then we function according to the DeleteRule of the foriegnkey.\r
-\r
-\r
- // 1. find if this row is attached to dataset.\r
- // 2. find if EnforceConstraints is true.\r
- // 3. find if there are any constraint on the table that the row is in.\r
- if (_table.DataSet != null && _table.DataSet.EnforceConstraints && _table.Constraints.Count > 0)\r
- {\r
- foreach (DataTable table in _table.DataSet.Tables)\r
- {\r
- // loop on all constraints of the table.\r
- ConstraintCollection constraintsCollection = table.Constraints;\r
- for (int i = 0; i < constraintsCollection.Count; i++)\r
- {\r
- ForeignKeyConstraint fk = null;\r
- if (constraintsCollection[i] is ForeignKeyConstraint)\r
- {\r
- fk = (ForeignKeyConstraint)constraintsCollection[i];\r
- if (fk.RelatedTable == _table)\r
- {\r
- //we create a dummy relation because we do not want to duplicate code of GetChild().\r
- // we use the dummy relation to find child rows.\r
- DataRelation rel = new DataRelation("dummy", fk.RelatedColumns, fk.Columns, false);\r
- Rule rule;\r
- if (action == DataRowAction.Delete)\r
- rule = fk.DeleteRule;\r
- else\r
- rule = fk.UpdateRule;\r
- CheckChildRows(rel, action, rule);\r
- }\r
- } \r
- }\r
- }\r
- }\r
- }\r
-\r
- private void CheckChildRows(DataRelation rel, DataRowAction action, Rule rule)\r
- { \r
- DataRow[] childRows = GetChildRows(rel);\r
- switch (rule)\r
+
+
+ /// <summary>
+ /// Gets or sets the custom error description for a row.
+ /// </summary>
+ public string RowError {
+ get { return rowError; }
+ set { rowError = value; }
+ }
+
+ /// <summary>
+ /// Gets the current state of the row in regards to its relationship to the
+ /// DataRowCollection.
+ /// </summary>
+ public DataRowState RowState {
+ get { return rowState; }
+ }
+
+ //FIXME?: Couldn't find a way to set the RowState when adding the DataRow
+ //to a Datatable so I added this method. Delete if there is a better way.
+ internal void AttachRow() {
+ current = proposed;
+ proposed = null;
+ rowState = DataRowState.Added;
+ }
+
+ //FIXME?: Couldn't find a way to set the RowState when removing the DataRow
+ //from a Datatable so I added this method. Delete if there is a better way.
+ internal void DetachRow() {
+ proposed = null;
+ _hasParentCollection = false;
+ rowState = DataRowState.Detached;
+ }
+
+ /// <summary>
+ /// Gets the DataTable for which this row has a schema.
+ /// </summary>
+ public DataTable Table {
+ get { return _table; }
+ }
+
+ /// <summary>
+ /// Gets and sets index of row. This is used from
+ /// XmlDataDocument.
+ // </summary>
+ internal int XmlRowID {
+ get { return xmlRowID; }
+ set { xmlRowID = value; }
+ }
+
+ #endregion
+
+ #region Methods
+
+ /// <summary>
+ /// Commits all the changes made to this row since the last time AcceptChanges was
+ /// called.
+ /// </summary>
+ public void AcceptChanges ()
+ {
+ EndEdit(); // in case it hasn't been called
+ switch (rowState) {
+ case DataRowState.Added:
+ case DataRowState.Modified:
+ rowState = DataRowState.Unchanged;
+ break;
+ case DataRowState.Deleted:
+ _table.Rows.Remove (this);
+ break;
+ case DataRowState.Detached:
+ throw new RowNotInTableException("Cannot perform this operation on a row not in the table.");
+ }
+ // Accept from detached
+ if (original == null)
+ original = new object[_table.Columns.Count];
+ Array.Copy (current, original, _table.Columns.Count);
+ }
+
+ /// <summary>
+ /// Begins an edit operation on a DataRow object.
+ /// </summary>
+ [MonoTODO]
+ public void BeginEdit ()
+ {
+ if (rowState == DataRowState.Deleted)
+ throw new DeletedRowInaccessibleException ();
+ if (!HasVersion (DataRowVersion.Proposed)) {
+ proposed = new object[_table.Columns.Count];
+ Array.Copy (current, proposed, current.Length);
+ }
+ //TODO: Suspend validation
+ editing = true;
+ }
+
+ /// <summary>
+ /// Cancels the current edit on the row.
+ /// </summary>
+ [MonoTODO]
+ public void CancelEdit ()
+ {
+ editing = false;
+ //TODO: Events
+ if (HasVersion (DataRowVersion.Proposed)) {
+ proposed = null;
+ if (rowState == DataRowState.Modified)
+ rowState = DataRowState.Unchanged;
+ }
+ }
+
+ /// <summary>
+ /// Clears the errors for the row, including the RowError and errors set with
+ /// SetColumnError.
+ /// </summary>
+ public void ClearErrors ()
+ {
+ rowError = String.Empty;
+ columnErrors = new String[_table.Columns.Count];
+ }
+
+ /// <summary>
+ /// Deletes the DataRow.
+ /// </summary>
+ [MonoTODO]
+ public void Delete ()
+ {
+ switch (rowState) {
+ case DataRowState.Added:
+ Table.Rows.Remove (this);
+ break;
+ case DataRowState.Deleted:
+ throw new DeletedRowInaccessibleException ();
+ default:
+ _table.DeletingDataRow(this, DataRowAction.Delete);
+ // check what to do with child rows
+ CheckChildRows(DataRowAction.Delete);
+ rowState = DataRowState.Deleted;
+ _table.DeletedDataRow(this, DataRowAction.Delete);
+ break;
+ }
+ }
+
+ // check the child rows of this row before deleting the row.
+ private void CheckChildRows(DataRowAction action)
+ {
+
+ // in this method we find the row that this row is in a reltion with them.
+ // in shortly we find all child rows of this row.
+ // then we function according to the DeleteRule of the foriegnkey.
+
+
+ // 1. find if this row is attached to dataset.
+ // 2. find if EnforceConstraints is true.
+ // 3. find if there are any constraint on the table that the row is in.
+ if (_table.DataSet != null && _table.DataSet.EnforceConstraints && _table.Constraints.Count > 0)
+ {
+ foreach (DataTable table in _table.DataSet.Tables)
+ {
+ // loop on all constraints of the table.
+ ConstraintCollection constraintsCollection = table.Constraints;
+ for (int i = 0; i < constraintsCollection.Count; i++)
+ {
+ ForeignKeyConstraint fk = null;
+ if (constraintsCollection[i] is ForeignKeyConstraint)
+ {
+ fk = (ForeignKeyConstraint)constraintsCollection[i];
+ if (fk.RelatedTable == _table)
+ {
+ //we create a dummy relation because we do not want to duplicate code of GetChild().
+ // we use the dummy relation to find child rows.
+ DataRelation rel = new DataRelation("dummy", fk.RelatedColumns, fk.Columns, false);
+ Rule rule;
+ if (action == DataRowAction.Delete)
+ rule = fk.DeleteRule;
+ else
+ rule = fk.UpdateRule;
+ CheckChildRows(rel, action, rule);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void CheckChildRows(DataRelation rel, DataRowAction action, Rule rule)
+ {
+ DataRow[] childRows = GetChildRows(rel);
+ switch (rule)
+ {
+ case Rule.Cascade: // delete or change all relted rows.
+ if (childRows != null)
+ {
+ for (int j = 0; j < childRows.Length; j++)
+ {
+ // if action is delete we delete all child rows
+ if (action == DataRowAction.Delete)
+ {
+ if (childRows[j].RowState != DataRowState.Deleted)
+ childRows[j].Delete();
+ }
+ // if action is change we change the values in the child row
+ else if (action == DataRowAction.Change)
+ {
+ // change only the values in the key columns
+ // set the childcolumn value to the new parent row value
+ for (int k = 0; k < rel.ChildColumns.Length; k++)
+ childRows[j][rel.ChildColumns[k]] = this[rel.ParentColumns[k], DataRowVersion.Proposed];
+ }
+ }
+ }
+ break;
+ case Rule.None: // throw an exception if there are any child rows.
+ if (childRows != null)
+ {
+ for (int j = 0; j < childRows.Length; j++)
+ {
+ if (childRows[j].RowState != DataRowState.Deleted)
+ {
+ string changeStr = "Cannot change this row because constraints are enforced on relation " + rel.RelationName +", and changing this row will strand child rows.";
+ string delStr = "Cannot delete this row because constraints are enforced on relation " + rel.RelationName +", and deleting this row will strand child rows.";
+ string message = action == DataRowAction.Delete ? delStr : changeStr;
+ throw new InvalidConstraintException(message);
+ }
+ }
+ }
+ break;
+ case Rule.SetDefault: // set the values in the child rows to the defult value of the columns.
+ if (childRows != null)
+ {
+ for (int j = 0; j < childRows.Length; j++)
+ {
+ DataRow child = childRows[j];
+ if (childRows[j].RowState != DataRowState.Deleted)
+ {
+ //set only the key columns to default
+ for (int k = 0; k < rel.ChildColumns.Length; k++)
+ child[rel.ChildColumns[k]] = rel.ChildColumns[k].DefaultValue;
+ }
+ }
+ }
+ break;
+ case Rule.SetNull: // set the values in the child row to null.
+ if (childRows != null)
+ {
+ for (int j = 0; j < childRows.Length; j++)
+ {
+ DataRow child = childRows[j];
+ if (childRows[j].RowState != DataRowState.Deleted)
+ {
+ // set only the key columns to DBNull
+ for (int k = 0; k < rel.ChildColumns.Length; k++)
+ child.SetNull(rel.ChildColumns[k]);
+ }
+ }
+ }
+ break;
+ }
+
+ }
+
+ /// <summary>
+ /// Ends the edit occurring on the row.
+ /// </summary>
+ [MonoTODO]
+ public void EndEdit ()
+ {
+ if (rowState == DataRowState.Detached)\r
{\r
- case Rule.Cascade: // delete or change all relted rows.\r
- if (childRows != null)\r
- {\r
- for (int j = 0; j < childRows.Length; j++)\r
- {\r
- // if action is delete we delete all child rows\r
- if (action == DataRowAction.Delete)\r
- {\r
- if (childRows[j].RowState != DataRowState.Deleted)\r
- childRows[j].Delete();\r
- }\r
- // if action is change we change the values in the child row\r
- else if (action == DataRowAction.Change)\r
- {\r
- // change only the values in the key columns\r
- // set the childcolumn value to the new parent row value\r
- for (int k = 0; k < rel.ChildColumns.Length; k++)\r
- childRows[j][rel.ChildColumns[k]] = this[rel.ParentColumns[k], DataRowVersion.Proposed];\r
- }\r
- }\r
- }\r
- break;\r
- case Rule.None: // throw an exception if there are any child rows.\r
- if (childRows != null)\r
- {\r
- for (int j = 0; j < childRows.Length; j++)\r
- {\r
- if (childRows[j].RowState != DataRowState.Deleted)\r
- {\r
- string changeStr = "Cannot change this row because constraints are enforced on relation " + rel.RelationName +", and changing this row will strand child rows.";\r
- string delStr = "Cannot delete this row because constraints are enforced on relation " + rel.RelationName +", and deleting this row will strand child rows.";\r
- string message = action == DataRowAction.Delete ? delStr : changeStr;\r
- throw new InvalidConstraintException(message);\r
- }\r
- }\r
- }\r
- break;\r
- case Rule.SetDefault: // set the values in the child rows to the defult value of the columns.\r
- if (childRows != null)\r
- {\r
- for (int j = 0; j < childRows.Length; j++)\r
- {\r
- DataRow child = childRows[j];\r
- if (childRows[j].RowState != DataRowState.Deleted)\r
- {\r
- //set only the key columns to default\r
- for (int k = 0; k < rel.ChildColumns.Length; k++)\r
- child[rel.ChildColumns[k]] = rel.ChildColumns[k].DefaultValue;\r
- }\r
- }\r
- }\r
- break;\r
- case Rule.SetNull: // set the values in the child row to null.\r
- if (childRows != null)\r
- {\r
- for (int j = 0; j < childRows.Length; j++)\r
- {\r
- DataRow child = childRows[j];\r
- if (childRows[j].RowState != DataRowState.Deleted)\r
- {\r
- // set only the key columns to DBNull\r
- for (int k = 0; k < rel.ChildColumns.Length; k++)\r
- child.SetNull(rel.ChildColumns[k]);\r
- }\r
- }\r
- }\r
- break;\r
+ editing = false;\r
+ return;\r
}\r
\r
- }\r
-\r
- /// <summary>\r
- /// Ends the edit occurring on the row.\r
- /// </summary>\r
- [MonoTODO]\r
- public void EndEdit () \r
- {\r
- editing = false;\r
- if (rowState == DataRowState.Detached)\r
- return;\r
if (HasVersion (DataRowVersion.Proposed))\r
{\r
_table.ChangingDataRow(this, DataRowAction.Change);\r
//and ForeignKeys.\r
try\r
{\r
- if (_table.DataSet == null || _table.DataSet.EnforceConstraints)\r
+ if ((_table.DataSet == null || _table.DataSet.EnforceConstraints) && !_table._duringDataLoad)\r
_table.Rows.ValidateDataRowInternal(this);\r
}\r
catch (Exception e)\r
{\r
+ editing = false;\r
proposed = null;\r
throw e;\r
}\r
CheckChildRows(DataRowAction.Change);\r
current = proposed;\r
proposed = null;\r
+ editing = false;\r
_table.ChangedDataRow(this, DataRowAction.Change);\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Gets the child rows of this DataRow using the specified DataRelation.\r
- /// </summary>\r
- public DataRow[] GetChildRows (DataRelation relation) \r
- {\r
- return GetChildRows (relation, DataRowVersion.Current);\r
- }\r
-\r
- /// <summary>\r
- /// Gets the child rows of a DataRow using the specified RelationName of a\r
- /// DataRelation.\r
- /// </summary>\r
- public DataRow[] GetChildRows (string relationName) \r
- {\r
- return GetChildRows (Table.DataSet.Relations[relationName]);\r
- }\r
-\r
- /// <summary>\r
- /// Gets the child rows of a DataRow using the specified DataRelation, and\r
- /// DataRowVersion.\r
- /// </summary>\r
- public DataRow[] GetChildRows (DataRelation relation, DataRowVersion version) \r
- {\r
- if (relation == null)\r
- return new DataRow[0];\r
-\r
- if (this.Table == null)\r
- throw new RowNotInTableException();\r
-\r
- if (relation.DataSet != this.Table.DataSet)\r
- throw new ArgumentException();\r
-\r
- // TODO: Caching for better preformance\r
- ArrayList rows = new ArrayList();\r
- DataColumn[] parentColumns = relation.ParentColumns;\r
- DataColumn[] childColumns = relation.ChildColumns;\r
- int numColumn = parentColumns.Length;\r
- if (HasVersion(version)) \r
- {\r
- foreach (DataRow row in relation.ChildTable.Rows) \r
- {\r
- bool allColumnsMatch = false;\r
- if (row.HasVersion(DataRowVersion.Default))\r
- {\r
- allColumnsMatch = true;\r
- for (int columnCnt = 0; columnCnt < numColumn; ++columnCnt) \r
- {\r
- if (!this[parentColumns[columnCnt], version].Equals(\r
- row[childColumns[columnCnt], DataRowVersion.Default])) \r
- {\r
- allColumnsMatch = false;\r
- break;\r
- }\r
- }\r
- }\r
- if (allColumnsMatch) rows.Add(row);\r
- }\r
- }\r
- return rows.ToArray(typeof(DataRow)) as DataRow[];\r
- }\r
-\r
- /// <summary>\r
- /// Gets the child rows of a DataRow using the specified RelationName of a\r
- /// DataRelation, and DataRowVersion.\r
- /// </summary>\r
- public DataRow[] GetChildRows (string relationName, DataRowVersion version) \r
- {\r
- return GetChildRows (Table.DataSet.Relations[relationName], version);\r
- }\r
-\r
- /// <summary>\r
- /// Gets the error description of the specified DataColumn.\r
- /// </summary>\r
- public string GetColumnError (DataColumn column) \r
- {\r
- return GetColumnError (_table.Columns.IndexOf(column));\r
- }\r
-\r
- /// <summary>\r
- /// Gets the error description for the column specified by index.\r
- /// </summary>\r
- public string GetColumnError (int columnIndex) \r
- {\r
- if (columnIndex < 0 || columnIndex >= columnErrors.Length)\r
- throw new IndexOutOfRangeException ();\r
-\r
- string retVal = columnErrors[columnIndex];\r
- if (retVal == null)\r
- retVal = string.Empty;\r
- return retVal;\r
- }\r
-\r
- /// <summary>\r
- /// Gets the error description for the column, specified by name.\r
- /// </summary>\r
- public string GetColumnError (string columnName) \r
- {\r
- return GetColumnError (_table.Columns.IndexOf(columnName));\r
- }\r
-\r
- /// <summary>\r
- /// Gets an array of columns that have errors.\r
- /// </summary>\r
- public DataColumn[] GetColumnsInError () \r
- {\r
- ArrayList dataColumns = new ArrayList ();\r
-\r
- for (int i = 0; i < columnErrors.Length; i += 1)\r
- {\r
- if (columnErrors[i] != null && columnErrors[i] != String.Empty)\r
- dataColumns.Add (_table.Columns[i]);\r
- }\r
-\r
- return (DataColumn[])(dataColumns.ToArray (typeof(DataColumn)));\r
- }\r
-\r
- /// <summary>\r
- /// Gets the parent row of a DataRow using the specified DataRelation.\r
- /// </summary>\r
- public DataRow GetParentRow (DataRelation relation) \r
- {\r
- return GetParentRow (relation, DataRowVersion.Current);\r
- }\r
-\r
- /// <summary>\r
- /// Gets the parent row of a DataRow using the specified RelationName of a\r
- /// DataRelation.\r
- /// </summary>\r
- public DataRow GetParentRow (string relationName) \r
- {\r
- return GetParentRow (relationName, DataRowVersion.Current);\r
- }\r
-\r
- /// <summary>\r
- /// Gets the parent row of a DataRow using the specified DataRelation, and\r
- /// DataRowVersion.\r
- /// </summary>\r
- public DataRow GetParentRow (DataRelation relation, DataRowVersion version) \r
- {\r
- DataRow[] rows = GetParentRows(relation, version);\r
- if (rows.Length == 0) return null;\r
- return rows[0];\r
- }\r
-\r
- /// <summary>\r
- /// Gets the parent row of a DataRow using the specified RelationName of a \r
- /// DataRelation, and DataRowVersion.\r
- /// </summary>\r
- public DataRow GetParentRow (string relationName, DataRowVersion version) \r
- {\r
- return GetParentRow (Table.DataSet.Relations[relationName], version);\r
- }\r
-\r
- /// <summary>\r
- /// Gets the parent rows of a DataRow using the specified DataRelation.\r
- /// </summary>\r
- public DataRow[] GetParentRows (DataRelation relation) \r
- {\r
- return GetParentRows (relation, DataRowVersion.Current);\r
- }\r
-\r
- /// <summary>\r
- /// Gets the parent rows of a DataRow using the specified RelationName of a \r
- /// DataRelation.\r
- /// </summary>\r
- public DataRow[] GetParentRows (string relationName) \r
- {\r
- return GetParentRows (relationName, DataRowVersion.Current);\r
- }\r
-\r
- /// <summary>\r
- /// Gets the parent rows of a DataRow using the specified DataRelation, and\r
- /// DataRowVersion.\r
- /// </summary>\r
- public DataRow[] GetParentRows (DataRelation relation, DataRowVersion version) \r
- {\r
- // TODO: Caching for better preformance\r
- if (relation == null)\r
- return new DataRow[0];\r
-\r
- if (this.Table == null)\r
- throw new RowNotInTableException();\r
-\r
- if (relation.DataSet != this.Table.DataSet)\r
- throw new ArgumentException();\r
-\r
- ArrayList rows = new ArrayList();\r
- DataColumn[] parentColumns = relation.ParentColumns;\r
- DataColumn[] childColumns = relation.ChildColumns;\r
- int numColumn = parentColumns.Length;\r
- if (HasVersion(version))\r
- {\r
- foreach (DataRow row in relation.ParentTable.Rows) \r
- {\r
- bool allColumnsMatch = false;\r
- if (row.HasVersion(DataRowVersion.Default))\r
- {\r
- allColumnsMatch = true;\r
- for (int columnCnt = 0; columnCnt < numColumn; columnCnt++) \r
- {\r
- if (!this[childColumns[columnCnt], version].Equals(\r
- row[parentColumns[columnCnt], DataRowVersion.Default])) \r
- {\r
- allColumnsMatch = false;\r
- break;\r
- }\r
- }\r
- }\r
- if (allColumnsMatch) rows.Add(row);\r
- }\r
- }\r
- return rows.ToArray(typeof(DataRow)) as DataRow[];\r
- }\r
-\r
- /// <summary>\r
- /// Gets the parent rows of a DataRow using the specified RelationName of a \r
- /// DataRelation, and DataRowVersion.\r
- /// </summary>\r
- public DataRow[] GetParentRows (string relationName, DataRowVersion version) \r
- {\r
- return GetParentRows (Table.DataSet.Relations[relationName], version);\r
- }\r
-\r
- /// <summary>\r
- /// Gets a value indicating whether a specified version exists.\r
- /// </summary>\r
- public bool HasVersion (DataRowVersion version) \r
- {\r
- switch (version)\r
- {\r
- case DataRowVersion.Default:\r
- if (rowState == DataRowState.Deleted)\r
- return false;\r
- if (rowState == DataRowState.Detached)\r
- return proposed != null;\r
- return true;\r
- case DataRowVersion.Proposed:\r
- if (rowState == DataRowState.Deleted)\r
- return false;\r
- return (proposed != null);\r
- case DataRowVersion.Current:\r
- if (rowState == DataRowState.Deleted || rowState == DataRowState.Detached)\r
- return false;\r
- return (current != null);\r
- case DataRowVersion.Original:\r
- if (rowState == DataRowState.Detached)\r
- return false;\r
- return (original != null);\r
- }\r
- return false;\r
- }\r
-\r
- /// <summary>\r
- /// Gets a value indicating whether the specified DataColumn contains a null value.\r
- /// </summary>\r
- public bool IsNull (DataColumn column) \r
- {\r
- object o = this[column];\r
- return (o == null || o == DBNull.Value);\r
- }\r
-\r
- /// <summary>\r
- /// Gets a value indicating whether the column at the specified index contains a null\r
- /// value.\r
- /// </summary>\r
- public bool IsNull (int columnIndex) \r
- {\r
- object o = this[columnIndex];\r
- return (o == null || o == DBNull.Value);\r
- }\r
-\r
- /// <summary>\r
- /// Gets a value indicating whether the named column contains a null value.\r
- /// </summary>\r
- public bool IsNull (string columnName) \r
- {\r
- object o = this[columnName];\r
- return (o == null || o == DBNull.Value);\r
- }\r
-\r
- /// <summary>\r
- /// Gets a value indicating whether the specified DataColumn and DataRowVersion\r
- /// contains a null value.\r
- /// </summary>\r
- public bool IsNull (DataColumn column, DataRowVersion version) \r
- {\r
- object o = this[column, version];\r
- return (o == null || o == DBNull.Value);\r
- }\r
-\r
- /// <summary>\r
- /// Rejects all changes made to the row since AcceptChanges was last called.\r
- /// </summary>\r
- public void RejectChanges () \r
- {\r
- // If original is null, then nothing has happened since AcceptChanges\r
- // was last called. We have no "original" to go back to.\r
- if (original != null)\r
- {\r
- Array.Copy (original, current, _table.Columns.Count);\r
- \r
- _table.ChangedDataRow (this, DataRowAction.Rollback);\r
- CancelEdit ();\r
- switch (rowState)\r
- {\r
- case DataRowState.Added:\r
- _table.Rows.Remove (this);\r
- break;\r
- case DataRowState.Modified:\r
- rowState = DataRowState.Unchanged;\r
- break;\r
- case DataRowState.Deleted:\r
- rowState = DataRowState.Unchanged;\r
- break;\r
- } \r
- \r
- } \r
- else {\r
- // If rows are just loaded via Xml the original values are null.\r
- // So in this case we have to remove all columns.\r
- // FIXME: I'm not realy sure, does this break something else, but\r
- // if so: FIXME ;)\r
- \r
- if ((rowState & DataRowState.Added) > 0)\r
- _table.Rows.Remove (this);\r
- }\r
- }\r
-\r
- /// <summary>\r
- /// Sets the error description for a column specified as a DataColumn.\r
- /// </summary>\r
- public void SetColumnError (DataColumn column, string error) \r
- {\r
- SetColumnError (_table.Columns.IndexOf (column), error);\r
- }\r
-\r
- /// <summary>\r
- /// Sets the error description for a column specified by index.\r
- /// </summary>\r
- public void SetColumnError (int columnIndex, string error) \r
- {\r
- if (columnIndex < 0 || columnIndex >= columnErrors.Length)\r
- throw new IndexOutOfRangeException ();\r
- columnErrors[columnIndex] = error;\r
- }\r
-\r
- /// <summary>\r
- /// Sets the error description for a column specified by name.\r
- /// </summary>\r
- public void SetColumnError (string columnName, string error) \r
+ }
+ }
+
+ /// <summary>
+ /// Gets the child rows of this DataRow using the specified DataRelation.
+ /// </summary>
+ public DataRow[] GetChildRows (DataRelation relation)
+ {
+ return GetChildRows (relation, DataRowVersion.Current);
+ }
+
+ /// <summary>
+ /// Gets the child rows of a DataRow using the specified RelationName of a
+ /// DataRelation.
+ /// </summary>
+ public DataRow[] GetChildRows (string relationName)
+ {
+ return GetChildRows (Table.DataSet.Relations[relationName]);
+ }
+
+ /// <summary>
+ /// Gets the child rows of a DataRow using the specified DataRelation, and
+ /// DataRowVersion.
+ /// </summary>
+ public DataRow[] GetChildRows (DataRelation relation, DataRowVersion version)
+ {
+ if (relation == null)
+ return new DataRow[0];
+
+ if (this.Table == null)
+ throw new RowNotInTableException();
+
+ if (relation.DataSet != this.Table.DataSet)
+ throw new ArgumentException();
+
+ // TODO: Caching for better preformance
+ ArrayList rows = new ArrayList();
+ DataColumn[] parentColumns = relation.ParentColumns;
+ DataColumn[] childColumns = relation.ChildColumns;
+ int numColumn = parentColumns.Length;
+ if (HasVersion(version))
+ {
+ foreach (DataRow row in relation.ChildTable.Rows)
+ {
+ bool allColumnsMatch = false;
+ if (row.HasVersion(DataRowVersion.Default))
+ {
+ allColumnsMatch = true;
+ for (int columnCnt = 0; columnCnt < numColumn; ++columnCnt)
+ {
+ if (!this[parentColumns[columnCnt], version].Equals(
+ row[childColumns[columnCnt], DataRowVersion.Default]))
+ {
+ allColumnsMatch = false;
+ break;
+ }
+ }
+ }
+ if (allColumnsMatch) rows.Add(row);
+ }
+ }
+ return rows.ToArray(typeof(DataRow)) as DataRow[];
+ }
+
+ /// <summary>
+ /// Gets the child rows of a DataRow using the specified RelationName of a
+ /// DataRelation, and DataRowVersion.
+ /// </summary>
+ public DataRow[] GetChildRows (string relationName, DataRowVersion version)
+ {
+ return GetChildRows (Table.DataSet.Relations[relationName], version);
+ }
+
+ /// <summary>
+ /// Gets the error description of the specified DataColumn.
+ /// </summary>
+ public string GetColumnError (DataColumn column)
+ {
+ return GetColumnError (_table.Columns.IndexOf(column));
+ }
+
+ /// <summary>
+ /// Gets the error description for the column specified by index.
+ /// </summary>
+ public string GetColumnError (int columnIndex)
+ {
+ if (columnIndex < 0 || columnIndex >= columnErrors.Length)
+ throw new IndexOutOfRangeException ();
+
+ string retVal = columnErrors[columnIndex];
+ if (retVal == null)
+ retVal = string.Empty;
+ return retVal;
+ }
+
+ /// <summary>
+ /// Gets the error description for the column, specified by name.
+ /// </summary>
+ public string GetColumnError (string columnName)
+ {
+ return GetColumnError (_table.Columns.IndexOf(columnName));
+ }
+
+ /// <summary>
+ /// Gets an array of columns that have errors.
+ /// </summary>
+ public DataColumn[] GetColumnsInError ()
+ {
+ ArrayList dataColumns = new ArrayList ();
+
+ for (int i = 0; i < columnErrors.Length; i += 1)
+ {
+ if (columnErrors[i] != null && columnErrors[i] != String.Empty)
+ dataColumns.Add (_table.Columns[i]);
+ }
+
+ return (DataColumn[])(dataColumns.ToArray (typeof(DataColumn)));
+ }
+
+ /// <summary>
+ /// Gets the parent row of a DataRow using the specified DataRelation.
+ /// </summary>
+ public DataRow GetParentRow (DataRelation relation)
+ {
+ return GetParentRow (relation, DataRowVersion.Current);
+ }
+
+ /// <summary>
+ /// Gets the parent row of a DataRow using the specified RelationName of a
+ /// DataRelation.
+ /// </summary>
+ public DataRow GetParentRow (string relationName)
+ {
+ return GetParentRow (relationName, DataRowVersion.Current);
+ }
+
+ /// <summary>
+ /// Gets the parent row of a DataRow using the specified DataRelation, and
+ /// DataRowVersion.
+ /// </summary>
+ public DataRow GetParentRow (DataRelation relation, DataRowVersion version)
+ {
+ DataRow[] rows = GetParentRows(relation, version);
+ if (rows.Length == 0) return null;
+ return rows[0];
+ }
+
+ /// <summary>
+ /// Gets the parent row of a DataRow using the specified RelationName of a
+ /// DataRelation, and DataRowVersion.
+ /// </summary>
+ public DataRow GetParentRow (string relationName, DataRowVersion version)
+ {
+ return GetParentRow (Table.DataSet.Relations[relationName], version);
+ }
+
+ /// <summary>
+ /// Gets the parent rows of a DataRow using the specified DataRelation.
+ /// </summary>
+ public DataRow[] GetParentRows (DataRelation relation)
+ {
+ return GetParentRows (relation, DataRowVersion.Current);
+ }
+
+ /// <summary>
+ /// Gets the parent rows of a DataRow using the specified RelationName of a
+ /// DataRelation.
+ /// </summary>
+ public DataRow[] GetParentRows (string relationName)
+ {
+ return GetParentRows (relationName, DataRowVersion.Current);
+ }
+
+ /// <summary>
+ /// Gets the parent rows of a DataRow using the specified DataRelation, and
+ /// DataRowVersion.
+ /// </summary>
+ public DataRow[] GetParentRows (DataRelation relation, DataRowVersion version)
+ {
+ // TODO: Caching for better preformance
+ if (relation == null)
+ return new DataRow[0];
+
+ if (this.Table == null)
+ throw new RowNotInTableException();
+
+ if (relation.DataSet != this.Table.DataSet)
+ throw new ArgumentException();
+
+ ArrayList rows = new ArrayList();
+ DataColumn[] parentColumns = relation.ParentColumns;
+ DataColumn[] childColumns = relation.ChildColumns;
+ int numColumn = parentColumns.Length;
+ if (HasVersion(version))
+ {
+ foreach (DataRow row in relation.ParentTable.Rows)
+ {
+ bool allColumnsMatch = false;
+ if (row.HasVersion(DataRowVersion.Default))
+ {
+ allColumnsMatch = true;
+ for (int columnCnt = 0; columnCnt < numColumn; columnCnt++)
+ {
+ if (!this[childColumns[columnCnt], version].Equals(
+ row[parentColumns[columnCnt], DataRowVersion.Default]))
+ {
+ allColumnsMatch = false;
+ break;
+ }
+ }
+ }
+ if (allColumnsMatch) rows.Add(row);
+ }
+ }
+ return rows.ToArray(typeof(DataRow)) as DataRow[];
+ }
+
+ /// <summary>
+ /// Gets the parent rows of a DataRow using the specified RelationName of a
+ /// DataRelation, and DataRowVersion.
+ /// </summary>
+ public DataRow[] GetParentRows (string relationName, DataRowVersion version)
+ {
+ return GetParentRows (Table.DataSet.Relations[relationName], version);
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether a specified version exists.
+ /// </summary>
+ public bool HasVersion (DataRowVersion version)
+ {
+ switch (version)
+ {
+ case DataRowVersion.Default:
+ if (rowState == DataRowState.Deleted)
+ return false;
+ if (rowState == DataRowState.Detached)
+ return proposed != null;
+ return true;
+ case DataRowVersion.Proposed:
+ if (rowState == DataRowState.Deleted)
+ return false;
+ return (proposed != null);
+ case DataRowVersion.Current:
+ if (rowState == DataRowState.Deleted || rowState == DataRowState.Detached)
+ return false;
+ return (current != null);
+ case DataRowVersion.Original:
+ if (rowState == DataRowState.Detached)
+ return false;
+ return (original != null);
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the specified DataColumn contains a null value.
+ /// </summary>
+ public bool IsNull (DataColumn column)
+ {
+ object o = this[column];
+ return (o == null || o == DBNull.Value);
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the column at the specified index contains a null
+ /// value.
+ /// </summary>
+ public bool IsNull (int columnIndex)
+ {
+ object o = this[columnIndex];
+ return (o == null || o == DBNull.Value);
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the named column contains a null value.
+ /// </summary>
+ public bool IsNull (string columnName)
+ {
+ object o = this[columnName];
+ return (o == null || o == DBNull.Value);
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the specified DataColumn and DataRowVersion
+ /// contains a null value.
+ /// </summary>
+ public bool IsNull (DataColumn column, DataRowVersion version)
+ {
+ object o = this[column, version];
+ return (o == null || o == DBNull.Value);
+ }
+
+ /// <summary>
+ /// Rejects all changes made to the row since AcceptChanges was last called.
+ /// </summary>
+ public void RejectChanges ()
+ {
+ // If original is null, then nothing has happened since AcceptChanges
+ // was last called. We have no "original" to go back to.
+ if (original != null)
+ {
+ Array.Copy (original, current, _table.Columns.Count);
+
+ _table.ChangedDataRow (this, DataRowAction.Rollback);
+ CancelEdit ();
+ switch (rowState)
+ {
+ case DataRowState.Added:
+ _table.Rows.Remove (this);
+ break;
+ case DataRowState.Modified:
+ rowState = DataRowState.Unchanged;
+ break;
+ case DataRowState.Deleted:
+ rowState = DataRowState.Unchanged;
+ 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.Rows.Remove (this);
+ }
+ }
+
+ /// <summary>
+ /// Sets the error description for a column specified as a DataColumn.
+ /// </summary>
+ public void SetColumnError (DataColumn column, string error)
+ {
+ SetColumnError (_table.Columns.IndexOf (column), error);
+ }
+
+ /// <summary>
+ /// Sets the error description for a column specified by index.
+ /// </summary>
+ public void SetColumnError (int columnIndex, string error)
+ {
+ if (columnIndex < 0 || columnIndex >= columnErrors.Length)
+ throw new IndexOutOfRangeException ();
+ columnErrors[columnIndex] = error;
+ }
+
+ /// <summary>
+ /// Sets the error description for a column specified by name.
+ /// </summary>
+ public void SetColumnError (string columnName, string error)
+ {
+ SetColumnError (_table.Columns.IndexOf (columnName), error);
+ }
+
+ /// <summary>
+ /// Sets the value of the specified DataColumn to a null value.
+ /// </summary>
+ protected void SetNull (DataColumn column)
+ {
+ this[column] = DBNull.Value;
+ }
+
+ /// <summary>
+ /// Sets the parent row of a DataRow with specified new parent DataRow.
+ /// </summary>
+ [MonoTODO]
+ public void SetParentRow (DataRow parentRow)
+ {
+ SetParentRow(parentRow, null);
+ }
+
+ /// <summary>
+ /// Sets the parent row of a DataRow with specified new parent DataRow and
+ /// DataRelation.
+ /// </summary>
+ [MonoTODO]
+ public void SetParentRow (DataRow parentRow, DataRelation relation)
+ {
+ if (_table == null || parentRow.Table == null)
+ throw new RowNotInTableException();
+
+ if (parentRow != null && _table.DataSet != parentRow.Table.DataSet)
+ throw new ArgumentException();
+
+ BeginEdit();
+ if (relation == null)
+ {
+ foreach (DataRelation parentRel in _table.ParentRelations)
+ {
+ DataColumn[] childCols = parentRel.ChildKeyConstraint.Columns;
+ DataColumn[] parentCols = parentRel.ChildKeyConstraint.RelatedColumns;
+
+ for (int i = 0; i < parentCols.Length; i++)
+ {
+ if (parentRow == null)
+ this[childCols[i].Ordinal] = DBNull.Value;
+ else
+ this[childCols[i].Ordinal] = parentRow[parentCols[i]];
+ }
+
+ }
+ }
+ else
+ {
+ DataColumn[] childCols = relation.ChildKeyConstraint.Columns;
+ DataColumn[] parentCols = relation.ChildKeyConstraint.RelatedColumns;
+
+ for (int i = 0; i < parentCols.Length; i++)
+ {
+ if (parentRow == null)
+ this[childCols[i].Ordinal] = DBNull.Value;
+ else
+ this[childCols[i].Ordinal] = parentRow[parentCols[i]];
+ }
+ }
+ EndEdit();
+ }
+
+ //Copy all values of this DataaRow to the row parameter.
+ internal void CopyValuesToRow(DataRow row)
+ {
+
+ if (row == null)
+ throw new ArgumentNullException("row");
+ if (row == this)
+ throw new ArgumentException("'row' is the same as this object");
+
+ DataColumnCollection columns = Table.Columns;
+
+ for(int i = 0; i < columns.Count; i++){
+
+ string columnName = columns[i].ColumnName;
+ int index = row.Table.Columns.IndexOf(columnName);
+ //if a column with the same name exists in both rows copy the values
+ if(index != -1) {
+ if (HasVersion(DataRowVersion.Original))
+ {
+ if (row.original == null)
+ row.original = new object[row.Table.Columns.Count];
+ row.original[index] = row.SetColumnValue(original[i], index);
+ }
+ if (HasVersion(DataRowVersion.Current))
+ {
+ if (row.current == null)
+ row.current = new object[row.Table.Columns.Count];
+ row.current[index] = row.SetColumnValue(current[i], index);
+ }
+ if (HasVersion(DataRowVersion.Proposed))
+ {
+ if (row.proposed == null)
+ row.proposed = new object[row.Table.Columns.Count];
+ row.proposed[index] = row.SetColumnValue(proposed[i], index);
+ }
+
+ //Saving the current value as the column value
+ row[index] = row.current[index];
+
+ }
+ }
+
+ row.rowState = RowState;
+ row.RowError = RowError;
+ row.columnErrors = columnErrors;
+ }
+
+
+ public void CollectionChanged(object sender, System.ComponentModel.CollectionChangeEventArgs args)
+ {
+ // if a column is added we hava to add an additional value the
+ // the priginal, current and propoed arrays.
+ // this scenario can happened in merge operation.
+
+ if (args.Action == System.ComponentModel.CollectionChangeAction.Add)
+ {
+ object[] tmp;
+ if (current != null)
+ {
+ tmp = new object[current.Length + 1];
+ Array.Copy (current, tmp, current.Length);
+ tmp[tmp.Length - 1] = DBNull.Value;
+ current = tmp;
+ }
+ if (proposed != null)
+ {
+ tmp = new object[proposed.Length + 1];
+ Array.Copy (proposed, tmp, proposed.Length);
+ tmp[tmp.Length - 1] = DBNull.Value;
+ proposed = tmp;
+ }
+ if(original != null)
+ {
+ tmp = new object[original.Length + 1];
+ Array.Copy (original, tmp, original.Length);
+ tmp[tmp.Length - 1] = DBNull.Value;
+ original = tmp;
+ }
+
+ }
+ }
+
+ internal bool IsRowChanged(DataRowState rowState) {
+ if((RowState & rowState) != 0)
+ return true;
+
+ //we need to find if child rows of this row changed.
+ //if yes - we should return true
+
+ // if the rowState is deleted we should get the original version of the row
+ // else - we should get the current version of the row.
+ DataRowVersion version = (rowState == DataRowState.Deleted) ? DataRowVersion.Original : DataRowVersion.Current;
+ int count = Table.ChildRelations.Count;
+ for (int i = 0; i < count; i++){
+ DataRelation rel = Table.ChildRelations[i];
+ DataRow[] childRows = GetChildRows(rel, version);
+ for (int j = 0; j < childRows.Length; j++){
+ if (childRows[j].IsRowChanged(rowState))
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ internal bool HasParentCollection
+ {
+ get
+ {
+ return _hasParentCollection;
+ }
+ set
+ {
+ _hasParentCollection = value;
+ }
+ }
+
+ internal void CheckNullConstraints()\r
{\r
- SetColumnError (_table.Columns.IndexOf (columnName), error);\r
- }\r
-\r
- /// <summary>\r
- /// Sets the value of the specified DataColumn to a null value.\r
- /// </summary>\r
- protected void SetNull (DataColumn column) \r
- {\r
- this[column] = DBNull.Value;\r
- }\r
-\r
- /// <summary>\r
- /// Sets the parent row of a DataRow with specified new parent DataRow.\r
- /// </summary>\r
- [MonoTODO]\r
- public void SetParentRow (DataRow parentRow) \r
- {\r
- SetParentRow(parentRow, null);\r
- }\r
-\r
- /// <summary>\r
- /// Sets the parent row of a DataRow with specified new parent DataRow and\r
- /// DataRelation.\r
- /// </summary>\r
- [MonoTODO]\r
- public void SetParentRow (DataRow parentRow, DataRelation relation) \r
- {\r
- if (_table == null || parentRow.Table == null)\r
- throw new RowNotInTableException();\r
-\r
- if (parentRow != null && _table.DataSet != parentRow.Table.DataSet)\r
- throw new ArgumentException();\r
- \r
- BeginEdit();\r
- if (relation == null)\r
+ if (_nullConstraintViolation)\r
{\r
- foreach (DataRelation parentRel in _table.ParentRelations)\r
+ for (int i = 0; i < proposed.Length; i++)\r
{\r
- DataColumn[] childCols = parentRel.ChildKeyConstraint.Columns;\r
- DataColumn[] parentCols = parentRel.ChildKeyConstraint.RelatedColumns;\r
- \r
- for (int i = 0; i < parentCols.Length; i++)\r
- {\r
- if (parentRow == null)\r
- this[childCols[i].Ordinal] = DBNull.Value;\r
- else\r
- this[childCols[i].Ordinal] = parentRow[parentCols[i]];\r
- }\r
- \r
- }\r
- }\r
- else\r
- {\r
- DataColumn[] childCols = relation.ChildKeyConstraint.Columns;\r
- DataColumn[] parentCols = relation.ChildKeyConstraint.RelatedColumns;\r
- \r
- for (int i = 0; i < parentCols.Length; i++)\r
- {\r
- if (parentRow == null)\r
- this[childCols[i].Ordinal] = DBNull.Value;\r
- else\r
- this[childCols[i].Ordinal] = parentRow[parentCols[i]];\r
+ if (this[i] == DBNull.Value && !_table.Columns[i].AllowDBNull)\r
+ throw new NoNullAllowedException(_nullConstraintMessage);\r
}\r
+ _nullConstraintViolation = false;\r
}\r
- EndEdit();\r
- }\r
- \r
- //Copy all values of this DataaRow to the row parameter.\r
- internal void CopyValuesToRow(DataRow row)\r
- {\r
- \r
- if (row == null)\r
- throw new ArgumentNullException("row");\r
- if (row == this)\r
- throw new ArgumentException("'row' is the same as this object");\r
-\r
- DataColumnCollection columns = Table.Columns;\r
- \r
- for(int i = 0; i < columns.Count; i++){\r
-\r
- string columnName = columns[i].ColumnName;\r
- int index = row.Table.Columns.IndexOf(columnName);\r
- //if a column with the same name exists in both rows copy the values\r
- if(index != -1) {\r
- if (HasVersion(DataRowVersion.Original))\r
- {\r
- if (row.original == null)\r
- row.original = new object[row.Table.Columns.Count];\r
- row.original[index] = row.SetColumnValue(original[i], index);\r
- }\r
- if (HasVersion(DataRowVersion.Current))\r
- {\r
- if (row.current == null)\r
- row.current = new object[row.Table.Columns.Count];\r
- row.current[index] = row.SetColumnValue(current[i], index);\r
- }\r
- if (HasVersion(DataRowVersion.Proposed))\r
- {\r
- if (row.proposed == null)\r
- row.proposed = new object[row.Table.Columns.Count];\r
- row.proposed[index] = row.SetColumnValue(proposed[i], index);\r
- }\r
- \r
- //Saving the current value as the column value\r
- row[index] = row.current[index];\r
- \r
- }\r
- }\r
-\r
- row.rowState = RowState;\r
- row.RowError = RowError;\r
- row.columnErrors = columnErrors;\r
- }\r
-\r
- \r
- public void CollectionChanged(object sender, System.ComponentModel.CollectionChangeEventArgs args)\r
- {\r
- // if a column is added we hava to add an additional value the \r
- // the priginal, current and propoed arrays.\r
- // this scenario can happened in merge operation.\r
-\r
- if (args.Action == System.ComponentModel.CollectionChangeAction.Add)\r
- {\r
- object[] tmp;\r
- if (current != null)\r
- {\r
- tmp = new object[current.Length + 1];\r
- Array.Copy (current, tmp, current.Length);\r
- tmp[tmp.Length - 1] = DBNull.Value;\r
- current = tmp;\r
- }\r
- if (proposed != null)\r
- {\r
- tmp = new object[proposed.Length + 1];\r
- Array.Copy (proposed, tmp, proposed.Length);\r
- tmp[tmp.Length - 1] = DBNull.Value;\r
- proposed = tmp;\r
- }\r
- if(original != null)\r
- {\r
- tmp = new object[original.Length + 1];\r
- Array.Copy (original, tmp, original.Length);\r
- tmp[tmp.Length - 1] = DBNull.Value;\r
- original = tmp;\r
- }\r
-\r
- }\r
- }\r
-\r
- internal bool IsRowChanged(DataRowState rowState) {\r
- if((RowState & rowState) != 0)\r
- return true;\r
-\r
- //we need to find if child rows of this row changed.\r
- //if yes - we should return true\r
-\r
- // if the rowState is deleted we should get the original version of the row\r
- // else - we should get the current version of the row.\r
- DataRowVersion version = (rowState == DataRowState.Deleted) ? DataRowVersion.Original : DataRowVersion.Current;\r
- int count = Table.ChildRelations.Count;\r
- for (int i = 0; i < count; i++){\r
- DataRelation rel = Table.ChildRelations[i];\r
- DataRow[] childRows = GetChildRows(rel, version);\r
- for (int j = 0; j < childRows.Length; j++){\r
- if (childRows[j].IsRowChanged(rowState))\r
- return true;\r
- }\r
- }\r
-\r
- return false;\r
- }\r
-\r
- internal bool HasParentCollection\r
- {\r
- get\r
- {\r
- return _hasParentCollection;\r
- }\r
- set\r
- {\r
- _hasParentCollection = value;\r
- }\r
- }\r
-\r
- #endregion // Methods\r
- }\r
-\r
- \r
-\r
-}\r
+ }
+
+ #endregion // Methods
+ }
+
+
+
+}