PageRenderTime 39ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/System.Data/System.Data/DataRowCollection.cs

https://bitbucket.org/danipen/mono
C# | 351 lines | 211 code | 51 blank | 89 comment | 67 complexity | a60ad0b206da7385ce94e789daa83342 MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. //
  2. // System.Data.DataRowCollection.cs
  3. //
  4. // Author:
  5. // Daniel Morgan <danmorg@sc.rr.com>
  6. // Tim Coleman <tim@timcoleman.com>
  7. //
  8. // (C) Ximian, Inc 2002
  9. // (C) Copyright 2002 Tim Coleman
  10. // (C) Copyright 2002 Daniel Morgan
  11. //
  12. //
  13. // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
  14. //
  15. // Permission is hereby granted, free of charge, to any person obtaining
  16. // a copy of this software and associated documentation files (the
  17. // "Software"), to deal in the Software without restriction, including
  18. // without limitation the rights to use, copy, modify, merge, publish,
  19. // distribute, sublicense, and/or sell copies of the Software, and to
  20. // permit persons to whom the Software is furnished to do so, subject to
  21. // the following conditions:
  22. //
  23. // The above copyright notice and this permission notice shall be
  24. // included in all copies or substantial portions of the Software.
  25. //
  26. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  27. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  28. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  29. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  30. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  31. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  32. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  33. //
  34. using System;
  35. using System.Collections;
  36. using System.ComponentModel;
  37. using System.Data.Common;
  38. namespace System.Data
  39. {
  40. /// <summary>
  41. /// Collection of DataRows in a DataTable
  42. /// </summary>
  43. public partial class DataRowCollection : InternalDataCollectionBase {
  44. private DataTable table;
  45. internal event ListChangedEventHandler ListChanged;
  46. /// <summary>
  47. /// Internal constructor used to build a DataRowCollection.
  48. /// </summary>
  49. internal DataRowCollection (DataTable table)
  50. {
  51. this.table = table;
  52. }
  53. /// <summary>
  54. /// Gets the row at the specified index.
  55. /// </summary>
  56. public DataRow this [int index] {
  57. get {
  58. if (index < 0 || index >= Count)
  59. throw new IndexOutOfRangeException ("There is no row at position " + index + ".");
  60. return (DataRow) List [index];
  61. }
  62. }
  63. /// <summary>
  64. /// Adds the specified DataRow to the DataRowCollection object.
  65. /// </summary>
  66. public void Add (DataRow row)
  67. {
  68. //TODO: validation
  69. if (row == null)
  70. throw new ArgumentNullException ("row", "'row' argument cannot be null.");
  71. if (row.Table != this.table)
  72. throw new ArgumentException ("This row already belongs to another table.");
  73. // If row id is not -1, we know that it is in the collection.
  74. if (row.RowID != -1)
  75. throw new ArgumentException ("This row already belongs to this table.");
  76. row.BeginEdit ();
  77. row.Validate ();
  78. AddInternal (row);
  79. }
  80. #if NET_2_0
  81. public
  82. #else
  83. internal
  84. #endif
  85. int IndexOf (DataRow row)
  86. {
  87. if (row == null || row.Table != table)
  88. return -1;
  89. int id = row.RowID;
  90. return (id >= 0 && id < List.Count && row == List [id]) ? id : -1;
  91. }
  92. internal void AddInternal (DataRow row)
  93. {
  94. AddInternal (row, DataRowAction.Add);
  95. }
  96. internal void AddInternal (DataRow row, DataRowAction action)
  97. {
  98. row.Table.ChangingDataRow (row, action);
  99. List.Add (row);
  100. row.AttachAt (List.Count - 1, action);
  101. row.Table.ChangedDataRow (row, action);
  102. if (row._rowChanged)
  103. row._rowChanged = false;
  104. }
  105. /// <summary>
  106. /// Creates a row using specified values and adds it to the DataRowCollection.
  107. /// </summary>
  108. public DataRow Add (params object[] values)
  109. {
  110. if (values == null)
  111. throw new NullReferenceException ();
  112. DataRow row = table.NewNotInitializedRow ();
  113. int newRecord = table.CreateRecord (values);
  114. row.ImportRecord (newRecord);
  115. row.Validate ();
  116. AddInternal (row);
  117. return row;
  118. }
  119. /// <summary>
  120. /// Clears the collection of all rows.
  121. /// </summary>
  122. public void Clear ()
  123. {
  124. if (this.table.DataSet != null && this.table.DataSet.EnforceConstraints) {
  125. foreach (Constraint c in table.Constraints) {
  126. UniqueConstraint uc = c as UniqueConstraint;
  127. if (uc == null)
  128. continue;
  129. if (uc.ChildConstraint == null || uc.ChildConstraint.Table.Rows.Count == 0)
  130. continue;
  131. string err = String.Format ("Cannot clear table Parent because " +
  132. "ForeignKeyConstraint {0} enforces Child.", uc.ConstraintName);
  133. throw new InvalidConstraintException (err);
  134. }
  135. }
  136. table.DataTableClearing ();
  137. List.Clear ();
  138. // Remove from indexes
  139. table.ResetIndexes ();
  140. table.DataTableCleared ();
  141. OnListChanged (this, new ListChangedEventArgs (ListChangedType.Reset, -1, -1));
  142. }
  143. /// <summary>
  144. /// Gets a value indicating whether the primary key of any row in the collection contains
  145. /// the specified value.
  146. /// </summary>
  147. public bool Contains (object key)
  148. {
  149. return Find (key) != null;
  150. }
  151. /// <summary>
  152. /// Gets a value indicating whether the primary key column(s) of any row in the
  153. /// collection contains the values specified in the object array.
  154. /// </summary>
  155. public bool Contains (object [] keys)
  156. {
  157. return Find (keys) != null;
  158. }
  159. /// <summary>
  160. /// Gets the row specified by the primary key value.
  161. /// </summary>
  162. public DataRow Find (object key)
  163. {
  164. return Find (new object []{key}, DataViewRowState.CurrentRows);
  165. }
  166. /// <summary>
  167. /// Gets the row containing the specified primary key values.
  168. /// </summary>
  169. public DataRow Find (object[] keys)
  170. {
  171. return Find (keys, DataViewRowState.CurrentRows);
  172. }
  173. /// <summary>
  174. /// Gets the row containing the specified primary key values by searching the rows
  175. /// filtered by the state.
  176. /// </summary>
  177. internal DataRow Find (object [] keys, DataViewRowState rowStateFilter)
  178. {
  179. if (table.PrimaryKey.Length == 0)
  180. throw new MissingPrimaryKeyException ("Table doesn't have a primary key.");
  181. if (keys == null)
  182. throw new ArgumentException ("Expecting " + table.PrimaryKey.Length +" value(s) for the key being indexed, but received 0 value(s).");
  183. Index index = table.GetIndex (table.PrimaryKey, null, rowStateFilter, null, false);
  184. int record = index.Find (keys);
  185. if (record != -1 || !table._duringDataLoad)
  186. return (record != -1 ? table.RecordCache [record] : null);
  187. // If the key is not found using Index *and* if DataTable is under BeginLoadData
  188. // then, check all the DataRows for the key
  189. record = table.RecordCache.NewRecord ();
  190. try {
  191. for (int i=0; i < table.PrimaryKey.Length; ++i)
  192. table.PrimaryKey [i].DataContainer [record] = keys [i];
  193. bool found;
  194. foreach (DataRow row in this) {
  195. int rowIndex = Key.GetRecord (row, rowStateFilter);
  196. if (rowIndex == -1)
  197. continue;
  198. found = true;
  199. for (int columnCnt = 0; columnCnt < table.PrimaryKey.Length; ++columnCnt) {
  200. if (table.PrimaryKey [columnCnt].CompareValues (rowIndex, record) == 0)
  201. continue;
  202. found = false;
  203. break;
  204. }
  205. if (found)
  206. return row;
  207. }
  208. return null;
  209. } finally {
  210. table.RecordCache.DisposeRecord (record);
  211. }
  212. }
  213. /// <summary>
  214. /// Inserts a new row into the collection at the specified location.
  215. /// </summary>
  216. public void InsertAt (DataRow row, int pos)
  217. {
  218. if (pos < 0)
  219. throw new IndexOutOfRangeException ("The row insert position " + pos + " is invalid.");
  220. if (row == null)
  221. throw new ArgumentNullException ("row", "'row' argument cannot be null.");
  222. if (row.Table != this.table)
  223. throw new ArgumentException ("This row already belongs to another table.");
  224. // If row id is not -1, we know that it is in the collection.
  225. if (row.RowID != -1)
  226. throw new ArgumentException ("This row already belongs to this table.");
  227. row.Validate ();
  228. row.Table.ChangingDataRow (row, DataRowAction.Add);
  229. if (pos >= List.Count) {
  230. pos = List.Count;
  231. List.Add (row);
  232. } else {
  233. List.Insert (pos, row);
  234. for (int i = pos+1; i < List.Count; i++)
  235. ((DataRow) List [i]).RowID = i;
  236. }
  237. row.AttachAt (pos, DataRowAction.Add);
  238. row.Table.ChangedDataRow (row, DataRowAction.Add);
  239. }
  240. /// <summary>
  241. /// Removes the specified DataRow from the internal list. Used by DataRow to commit the removing.
  242. /// </summary>
  243. internal void RemoveInternal (DataRow row)
  244. {
  245. if (row == null)
  246. throw new IndexOutOfRangeException ("The given datarow is not in the current DataRowCollection.");
  247. int index = List.IndexOf (row);
  248. if (index < 0)
  249. throw new IndexOutOfRangeException ("The given datarow is not in the current DataRowCollection.");
  250. List.RemoveAt (index);
  251. for (; index < List.Count; ++index)
  252. ((DataRow) List [index]).RowID = index;
  253. }
  254. /// <summary>
  255. /// Removes the specified DataRow from the collection.
  256. /// </summary>
  257. public void Remove (DataRow row)
  258. {
  259. if (IndexOf (row) < 0)
  260. throw new IndexOutOfRangeException ("The given datarow is not in the current DataRowCollection.");
  261. DataRowState state = row.RowState;
  262. if (state != DataRowState.Deleted && state != DataRowState.Detached) {
  263. row.Delete ();
  264. // if the row was in added state it will be in Detached state after the
  265. // delete operation, so we have to check it.
  266. if (row.RowState != DataRowState.Detached)
  267. row.AcceptChanges ();
  268. }
  269. }
  270. /// <summary>
  271. /// Removes the row at the specified index from the collection.
  272. /// </summary>
  273. public void RemoveAt (int index)
  274. {
  275. Remove (this [index]);
  276. }
  277. internal void OnListChanged (object sender, ListChangedEventArgs args)
  278. {
  279. if (ListChanged != null)
  280. ListChanged (sender, args);
  281. }
  282. }
  283. sealed partial class DataRowCollection {
  284. public override int Count {
  285. get { return List.Count; }
  286. }
  287. public void CopyTo (DataRow [] array, int index)
  288. {
  289. CopyTo ((Array) array, index);
  290. }
  291. public override void CopyTo (Array ar, int index)
  292. {
  293. base.CopyTo (ar, index);
  294. }
  295. public override IEnumerator GetEnumerator ()
  296. {
  297. return base.GetEnumerator ();
  298. }
  299. }
  300. }