// (C) Copyright 2002 Tim Coleman
//
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
using System;
using System.Collections;
using System.ComponentModel;
using System.Globalization;
+using System.IO;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters.Binary;
-namespace System.Data {
+namespace System.Data
+{
/// <summary>
/// Represents the collection of tables for the DataSet.
/// </summary>
- [Editor]
+ [Editor ("Microsoft.VSDesigner.Data.Design.TablesCollectionEditor, " + Consts.AssemblyMicrosoft_VSDesigner,
+ "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
[DefaultEvent ("CollectionChanged")]
[ListBindable (false)]
- [Serializable]
- public class DataTableCollection : InternalDataCollectionBase
- {
+ public partial class DataTableCollection : InternalDataCollectionBase {
DataSet dataSet;
-
- #region Constructors
+ DataTable[] mostRecentTables;
+
+ #region Constructors
internal DataTableCollection (DataSet dataSet)
: base ()
{
this.dataSet = dataSet;
}
-
+
#endregion
-
+
#region Properties
- public DataTable this[int index] {
- get { return (DataTable)(List[index]); }
+ public DataTable this [int index] {
+ get {
+ if (index < 0 || index >= List.Count)
+ throw new IndexOutOfRangeException (String.Format ("Cannot find table {0}", index));
+ return (DataTable)(List [index]);
+ }
}
- public DataTable this[string name] {
- get {
+ public DataTable this [string name] {
+ get {
int index = IndexOf (name, true);
- return index < 0 ? null : (DataTable) List[index];
+ return index < 0 ? null : (DataTable) List [index];
}
}
-#if NET_2_0
- [MonoTODO]
- public DataTable this [string name, string tbNamespace] {
- get { throw new NotImplementedException (); }
- }
-#endif
-
protected override ArrayList List {
get { return base.List; }
}
#endregion
-
- #region Methods
- public virtual DataTable Add ()
+ #region Methods
+
+ public
+#if !NET_2_0
+ virtual
+#endif
+ DataTable Add ()
{
DataTable Table = new DataTable ();
Add (Table);
return Table;
}
- public virtual void Add (DataTable table)
+ public
+#if !NET_2_0
+ virtual
+#endif
+ void Add (DataTable table)
{
-
+ OnCollectionChanging (new CollectionChangeEventArgs (CollectionChangeAction.Add, table));
// check if the reference is a null reference
- if(table == null)
- throw new ArgumentNullException("table");
-
+ if (table == null)
+ throw new ArgumentNullException ("table");
+
// check if the list already contains this tabe.
- if(List.Contains(table))
- throw new ArgumentException("DataTable already belongs to this DataSet.");
-
+ if (List.Contains (table))
+ throw new ArgumentException ("DataTable already belongs to this DataSet.");
+
+ // check if table is part of another DataSet
+ if (table.DataSet != null && table.DataSet != this.dataSet)
+ throw new ArgumentException ("DataTable already belongs to another DataSet");
+
// if the table name is null or empty string.
- // give her a name.
+ // give her a name.
if (table.TableName == null || table.TableName == string.Empty)
NameTable (table);
-
+
// check if the collection has a table with the same name.
- int tmp = IndexOf(table.TableName);
+#if !NET_2_0
+ int tmp = IndexOf (table.TableName);
+#else
+ int tmp = IndexOf (table.TableName, table.Namespace);
+#endif
// if we found a table with same name we have to check
// that it is the same case.
// indexof can return a table with different case letters.
- if (tmp != -1)
- {
- if(table.TableName == this[tmp].TableName)
- throw new DuplicateNameException("A DataTable named '" + table.TableName + "' already belongs to this DataSet.");
- }
-
+ if (tmp != -1 &&
+ table.TableName == this [tmp].TableName)
+ throw new DuplicateNameException ("A DataTable named '" + table.TableName + "' already belongs to this DataSet.");
+
List.Add (table);
table.dataSet = dataSet;
OnCollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, table));
}
- public virtual DataTable Add (string name)
+ public
+#if !NET_2_0
+ virtual
+#endif
+ DataTable Add (string name)
{
DataTable table = new DataTable (name);
this.Add (table);
return table;
}
-#if NET_2_0
- public virtual DataTable Add (string name, string tbNamespace)
+ public void AddRange (DataTable [] tables)
{
- DataTable table = new DataTable (name, tbNamespace);
- this.Add (table);
- return table;
+ if (dataSet != null && dataSet.InitInProgress) {
+ mostRecentTables = tables;
+ return;
+ }
+
+ if (tables == null)
+ return;
+
+ foreach (DataTable table in tables) {
+ if (table == null)
+ continue;
+ Add (table);
+ }
}
-#endif
- public void AddRange (DataTable[] tables)
+ internal void PostAddRange ()
{
- foreach (DataTable table in tables)
- this.Add (table);
+ if (mostRecentTables == null)
+ return;
+
+ foreach (DataTable table in mostRecentTables){
+ if (table == null)
+ continue;
+ Add (table);
+ }
+ mostRecentTables = null;
}
- public bool CanRemove (DataTable table)
+ public bool CanRemove (DataTable table)
{
- return CanRemove(table, false);
+ return CanRemove (table, false);
}
- public void Clear ()
+ public void Clear ()
{
List.Clear ();
}
- public bool Contains (string name)
+ public bool Contains (string name)
{
return (-1 != IndexOf (name, false));
}
- public virtual int IndexOf (DataTable table)
+ public
+#if !NET_2_0
+ virtual
+#endif
+ int IndexOf (DataTable table)
{
return List.IndexOf (table);
}
- public virtual int IndexOf (string name)
+ public
+#if !NET_2_0
+ virtual
+#endif
+ int IndexOf (string tableName)
{
- return IndexOf (name, false);
+ return IndexOf (tableName, false);
}
- public void Remove (DataTable table)
+ public void Remove (DataTable table)
{
- CanRemove(table, true);
- List.Remove(table);
+ OnCollectionChanging (new CollectionChangeEventArgs (CollectionChangeAction.Remove, table));
+ if (CanRemove (table, true))
+ table.dataSet = null;
+
+ List.Remove (table);
+ table.dataSet = null;
OnCollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, table));
}
- public void Remove (string name)
+ public void Remove (string name)
{
- Remove (this [name]);
+ int index = IndexOf (name, false);
+ if (index == -1)
+ throw new ArgumentException ("Table " + name + " does not belong to this DataSet");
+ RemoveAt (index);
}
- public void RemoveAt (int index)
+ public void RemoveAt (int index)
{
- if (( index < 0 ) || (index >=List.Count))
- throw new ArgumentException("There is no row at position "+index+".");
- DataTable t = this[index];
- CanRemove(t, true);
- List.RemoveAt (index);
- OnCollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, t));
+ Remove (this [index]);
}
#endregion
#region Protected methods
- protected internal virtual void OnCollectionChanging (CollectionChangeEventArgs Args)
+#if !NET_2_0
+ protected internal virtual
+#else
+ internal
+#endif
+ void OnCollectionChanging (CollectionChangeEventArgs ccevent)
{
if (CollectionChanging != null)
- CollectionChanging (this, Args);
+ CollectionChanging (this, ccevent);
}
- protected virtual void OnCollectionChanged (CollectionChangeEventArgs Args)
+#if !NET_2_0
+ protected virtual
+#else
+ internal
+#endif
+ void OnCollectionChanged (CollectionChangeEventArgs ccevent)
{
if (CollectionChanged != null)
- CollectionChanged (this, Args);
+ CollectionChanged (this, ccevent);
}
#endregion
#region Private methods
- private int IndexOf (string name, bool error)
+ private int IndexOf (string name, bool error, int start)
{
int count = 0, match = -1;
- for (int i = 0; i < List.Count; i++)
- {
+ for (int i = start; i < List.Count; i++) {
String name2 = ((DataTable) List[i]).TableName;
- if (String.Compare (name, name2, true) == 0)
- {
- if (String.Compare (name, name2, false) == 0)
- return i;
+ if (String.Compare (name, name2, false, dataSet.Locale) == 0)
+ return i;
+ if (String.Compare (name, name2, true, dataSet.Locale) == 0) {
match = i;
count++;
}
while (Contains (Name + i))
i++;
- Table.TableName = Name + i;
+ Table.TableName = Name + i;
}
-
+
// check if a table can be removed from this collectiuon.
// if the table can not be remved act according to throwException parameter.
// if it is true throws an Exception, else return false.
- private bool CanRemove(DataTable table, bool throwException)
+ private bool CanRemove (DataTable table, bool throwException)
{
-
// check if table is null reference
- if (table == null)
- {
- if(throwException)
- throw new ArgumentNullException("table");
+ if (table == null) {
+ if (throwException)
+ throw new ArgumentNullException ("table");
return false;
}
- // check if the table doesnot belong to this collection
- bool tableexists = true;
- int tmp = IndexOf(table.TableName);
- // if we found a table with same name we have to check
- // that it is the same case.
- // indexof can return a table with different case letters.
- if (tmp != -1)
- {
- if(table.TableName != this[tmp].TableName)
- tableexists = false;
- }
- else
- tableexists = false;
-
- if (!tableexists)
- {
- if(throwException)
- throw new ArgumentException("Table does not exist in collection");
- return false;
-
- }
-
-
// check if the table has the same DataSet as this collection.
- if(table.DataSet != this.dataSet)
- {
- if(throwException)
- throw new ArgumentException("Table " + table.TableName + " does not belong to this DataSet.");
- return false;
+ if (table.DataSet != this.dataSet) {
+ if (!throwException)
+ return false;
+ throw new ArgumentException ("Table " + table.TableName + " does not belong to this DataSet.");
}
-
+
// check the table has a relation attached to it.
- if (table.ParentRelations.Count > 0 || table.ChildRelations.Count > 0)
- {
- if(throwException)
- throw new ArgumentException("Cannot remove a table that has existing relations. Remove relations first.");
- return false;
+ if (table.ParentRelations.Count > 0 || table.ChildRelations.Count > 0) {
+ if (!throwException)
+ return false;
+ throw new ArgumentException ("Cannot remove a table that has existing relations. Remove relations first.");
}
-
// now we check if any ForeignKeyConstraint is referncing 'table'.
- IEnumerator tableEnumerator = this.dataSet.Tables.GetEnumerator();
-
- // loop on all tables in dataset
- while (tableEnumerator.MoveNext())
- {
- IEnumerator constraintEnumerator = ((DataTable) tableEnumerator.Current).Constraints.GetEnumerator();
- // loop on all constrains in the current table
- while (constraintEnumerator.MoveNext())
- {
- Object o = constraintEnumerator.Current;
- // we only check ForeignKeyConstraint
- if (o is ForeignKeyConstraint)
- {
- ForeignKeyConstraint fc = (ForeignKeyConstraint) o;
- if(fc.Table == table || fc.RelatedTable == table)
- {
- if(throwException)
- throw new ArgumentException("Cannot remove table " + table.TableName + ", because it referenced in ForeignKeyConstraint " + fc.ConstraintName + ". Remove the constraint first.");
- return false;
- }
- }
+ foreach (Constraint c in table.Constraints) {
+ UniqueConstraint uc = c as UniqueConstraint;
+ if (uc != null) {
+ if (uc.ChildConstraint == null)
+ continue;
+
+ if (!throwException)
+ return false;
+ RaiseForeignKeyReferenceException (table.TableName, uc.ChildConstraint.ConstraintName);
}
+
+ ForeignKeyConstraint fc = c as ForeignKeyConstraint;
+ if (fc == null)
+ continue;
+
+ if (!throwException)
+ return false;
+ RaiseForeignKeyReferenceException (table.TableName, fc.ConstraintName);
}
return true;
}
+ private void RaiseForeignKeyReferenceException (string table, string constraint)
+ {
+ throw new ArgumentException (String.Format ("Cannot remove table {0}, because it is referenced" +
+ " in ForeignKeyConstraint {1}. Remove the constraint first.",
+ table, constraint));
+ }
+
#endregion // Private methods
#region Events
- [ResDescriptionAttribute ("Occurs whenever this collection's membership changes.")]
+ [ResDescriptionAttribute ("Occurs whenever this collection's membership changes.")]
public event CollectionChangeEventHandler CollectionChanged;
public event CollectionChangeEventHandler CollectionChanging;
#endregion
}
+
+#if NET_2_0
+ sealed partial class DataTableCollection {
+ public DataTable this [string name, string tableNamespace] {
+ get {
+ int index = IndexOf (name, tableNamespace, true);
+ return index < 0 ? null : (DataTable) List [index];
+ }
+ }
+
+ public DataTable Add (string name, string tableNamespace)
+ {
+ DataTable table = new DataTable (name, tableNamespace);
+ this.Add (table);
+ return table;
+ }
+
+ public bool Contains (string name, string tableNamespace)
+ {
+ return (IndexOf (name, tableNamespace) != -1);
+ }
+
+ public int IndexOf (string tableName, string tableNamespace)
+ {
+ if (tableNamespace == null)
+ throw new ArgumentNullException ("'tableNamespace' argument cannot be null.",
+ "tableNamespace");
+ return IndexOf (tableName, tableNamespace, false);
+ }
+
+ public void Remove (string name, string tableNamespace)
+ {
+ int index = IndexOf (name, tableNamespace, true);
+ if (index == -1)
+ throw new ArgumentException ("Table " + name + " does not belong to this DataSet");
+
+ RemoveAt (index);
+ }
+
+ private int IndexOf (string name, string ns, bool error)
+ {
+ int index = -1, count = 0, match = -1;
+ do {
+ index = IndexOf (name, error, index+1);
+
+ if (index == -1)
+ break;
+
+ if (ns == null) {
+ if (count > 1)
+ break;
+ count++;
+ match = index;
+ } else if (this [index].Namespace.Equals (ns))
+ return index;
+
+ } while (index != -1 && index < Count);
+
+ if (count == 1)
+ return match;
+
+ if (count == 0 || !error)
+ return -1;
+
+ throw new ArgumentException ("The given name '" + name + "' matches atleast two names" +
+ "in the collection object with different namespaces");
+ }
+
+ private int IndexOf (string name, bool error)
+ {
+ return IndexOf (name, null, error);
+ }
+
+ public void CopyTo (DataTable [] array, int index)
+ {
+ CopyTo ((Array) array, index);
+ }
+
+ internal void BinarySerialize_Schema (SerializationInfo si)
+ {
+ si.AddValue ("DataSet.Tables.Count", Count);
+ for (int i = 0; i < Count; i++) {
+ DataTable dt = (DataTable) List [i];
+
+ if (dt.dataSet != dataSet)
+ throw new SystemException ("Internal Error: inconsistent DataTable");
+
+ MemoryStream ms = new MemoryStream ();
+ BinaryFormatter bf = new BinaryFormatter ();
+ bf.Serialize (ms, dt);
+ byte [] serializedStream = ms.ToArray ();
+ ms.Close ();
+ si.AddValue ("DataSet.Tables_" + i, serializedStream, typeof (Byte []));
+ }
+ }
+
+ internal void BinarySerialize_Data (SerializationInfo si)
+ {
+ for (int i = 0; i < Count; i++) {
+ DataTable dt = (DataTable) List [i];
+ for (int j = 0; j < dt.Columns.Count; j++) {
+ si.AddValue ("DataTable_" + i + ".DataColumn_" + j + ".Expression",
+ dt.Columns[j].Expression);
+ }
+ dt.BinarySerialize (si, "DataTable_" + i + ".");
+ }
+ }
+ }
+#else
+ [Serializable]
+ partial class DataTableCollection {
+ private int IndexOf (string name, bool error)
+ {
+ return IndexOf (name, error, 0);
+ }
+ }
+#endif
}