736 lines
22 KiB
C#
736 lines
22 KiB
C#
//
|
|
// System.Data.DataColumnCollection.cs
|
|
//
|
|
// Author:
|
|
// Christopher Podurgiel (cpodurgiel@msn.com)
|
|
// Stuart Caborn <stuart.caborn@virgin.net>
|
|
// Tim Coleman (tim@timcoleman.com)
|
|
//
|
|
// (C) Chris Podurgiel
|
|
// Copyright (C) Tim Coleman, 2002
|
|
// Copyright (C) Daniel Morgan, 2003
|
|
//
|
|
|
|
//
|
|
// 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.Text;
|
|
using System.Collections;
|
|
using System.ComponentModel;
|
|
|
|
namespace System.Data {
|
|
|
|
internal class Doublet
|
|
{
|
|
public Doublet (int count, string columnname)
|
|
{
|
|
this.count = count;
|
|
this.columnNames.Add (columnname);
|
|
}
|
|
// Number of case insensitive column name
|
|
public int count;
|
|
// Array of exact column names
|
|
public ArrayList columnNames = new ArrayList ();
|
|
}
|
|
|
|
[Editor ("Microsoft.VSDesigner.Data.Design.ColumnsCollectionEditor, " + Consts.AssemblyMicrosoft_VSDesigner,
|
|
"System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
|
|
#if !NET_2_0
|
|
[Serializable]
|
|
#endif
|
|
[DefaultEvent ("CollectionChanged")]
|
|
public
|
|
#if NET_2_0
|
|
sealed
|
|
#endif
|
|
class DataColumnCollection : InternalDataCollectionBase {
|
|
//This hashtable maps between unique case insensetive column name to a doublet containing column ref and column count
|
|
#if NET_2_0
|
|
private Hashtable columnNameCount = new Hashtable (StringComparer.OrdinalIgnoreCase);
|
|
#else
|
|
private Hashtable columnNameCount = new Hashtable (CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default);
|
|
#endif
|
|
//This hashtable maps between column name to DataColumn object.
|
|
private Hashtable columnFromName = new Hashtable ();
|
|
//This ArrayList contains the auto-increment columns names
|
|
private ArrayList autoIncrement = new ArrayList ();
|
|
//This holds the next index to use for default column name.
|
|
private int defaultColumnIndex = 1;
|
|
//table should be the DataTable this DataColumnCollection belongs to.
|
|
private DataTable parentTable = null;
|
|
// Keep reference to most recent columns passed to AddRange()
|
|
// so that they can be added when EndInit() is called.
|
|
DataColumn [] _mostRecentColumns = null;
|
|
|
|
static readonly string ColumnPrefix = "Column";
|
|
|
|
// Internal Constructor. This Class can only be created from other classes in this assembly.
|
|
internal DataColumnCollection (DataTable table)
|
|
{
|
|
parentTable = table;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the DataColumn from the collection at the specified index.
|
|
/// </summary>
|
|
public
|
|
#if !NET_2_0
|
|
virtual
|
|
#endif
|
|
DataColumn this [int index] {
|
|
get {
|
|
if (index < 0 || index >= base.List.Count)
|
|
throw new IndexOutOfRangeException ("Cannot find column " + index + ".");
|
|
return (DataColumn) base.List [index];
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the DataColumn from the collection with the specified name.
|
|
/// </summary>
|
|
public
|
|
#if !NET_2_0
|
|
virtual
|
|
#endif
|
|
DataColumn this [string name] {
|
|
get {
|
|
#if NET_2_0
|
|
if (name == null)
|
|
throw new ArgumentNullException ("name");
|
|
#endif
|
|
|
|
DataColumn dc = columnFromName [name] as DataColumn;
|
|
if (dc != null)
|
|
return dc;
|
|
|
|
int tmp = IndexOf (name, true);
|
|
return tmp == -1 ? null : (DataColumn) base.List [tmp];
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a list of the DataColumnCollection items.
|
|
/// </summary>
|
|
protected override ArrayList List {
|
|
get { return base.List; }
|
|
}
|
|
|
|
internal ArrayList AutoIncrmentColumns {
|
|
get { return autoIncrement; }
|
|
}
|
|
|
|
//Add Logic
|
|
//
|
|
//Changing Event
|
|
//DefaultValue set and AutoInc set check
|
|
//?Validate Expression??
|
|
//Name check and creation
|
|
//Set Table
|
|
//Check Unique if true then add a unique constraint
|
|
//?Notify Rows of new column ?
|
|
//Add to collection
|
|
//Changed Event
|
|
|
|
/// <summary>
|
|
/// Creates and adds a DataColumn object to the DataColumnCollection.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public
|
|
#if !NET_2_0
|
|
virtual
|
|
#endif
|
|
DataColumn Add ()
|
|
{
|
|
DataColumn column = new DataColumn (null);
|
|
Add (column);
|
|
return column;
|
|
}
|
|
|
|
#if NET_2_0
|
|
public void CopyTo (DataColumn [] array, int index)
|
|
{
|
|
CopyTo ((Array) array, index);
|
|
}
|
|
#endif
|
|
|
|
internal void RegisterName (string name, DataColumn column)
|
|
{
|
|
try {
|
|
columnFromName.Add (name, column);
|
|
} catch (ArgumentException) {
|
|
throw new DuplicateNameException ("A DataColumn named '" + name + "' already belongs to this DataTable.");
|
|
}
|
|
|
|
// Get existing doublet
|
|
Doublet d = (Doublet) columnNameCount [name];
|
|
if (d != null) {
|
|
// Add reference count
|
|
d.count++;
|
|
// Add a new name
|
|
d.columnNames.Add (name);
|
|
} else {
|
|
// no existing doublet
|
|
// create one
|
|
d = new Doublet (1, name);
|
|
columnNameCount [name] = d;
|
|
}
|
|
|
|
#if NET_2_0
|
|
if (name.Length <= ColumnPrefix.Length || !name.StartsWith (ColumnPrefix, StringComparison.Ordinal))
|
|
return;
|
|
#else
|
|
if (name.Length <= ColumnPrefix.Length || !name.StartsWith (ColumnPrefix))
|
|
return;
|
|
#endif
|
|
|
|
if (name == MakeName (defaultColumnIndex + 1)) {
|
|
do {
|
|
defaultColumnIndex++;
|
|
} while (Contains (MakeName (defaultColumnIndex + 1)));
|
|
}
|
|
}
|
|
|
|
internal void UnregisterName (string name)
|
|
{
|
|
if (columnFromName.Contains (name))
|
|
columnFromName.Remove (name);
|
|
|
|
// Get the existing doublet
|
|
Doublet d = (Doublet) columnNameCount [name];
|
|
if (d != null) {
|
|
// decrease reference count
|
|
d.count--;
|
|
d.columnNames.Remove (name);
|
|
// remove doublet if no more references
|
|
if (d.count == 0)
|
|
columnNameCount.Remove (name);
|
|
}
|
|
|
|
if (name.StartsWith(ColumnPrefix) && name == MakeName(defaultColumnIndex - 1)) {
|
|
do {
|
|
defaultColumnIndex--;
|
|
} while (!Contains (MakeName (defaultColumnIndex - 1)) && defaultColumnIndex > 1);
|
|
}
|
|
}
|
|
|
|
private string GetNextDefaultColumnName ()
|
|
{
|
|
string defColumnName = MakeName (defaultColumnIndex);
|
|
for (int index = defaultColumnIndex + 1; Contains (defColumnName); ++index) {
|
|
defColumnName = MakeName (index);
|
|
defaultColumnIndex++;
|
|
}
|
|
defaultColumnIndex++;
|
|
return defColumnName;
|
|
}
|
|
|
|
static readonly string[] TenColumns = { "Column0", "Column1", "Column2", "Column3", "Column4", "Column5", "Column6", "Column7", "Column8", "Column9" };
|
|
|
|
static string MakeName (int index)
|
|
{
|
|
if (index < 10)
|
|
return TenColumns [index];
|
|
return String.Concat (ColumnPrefix, index.ToString());
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates and adds the specified DataColumn object to the DataColumnCollection.
|
|
/// </summary>
|
|
/// <param name="column">The DataColumn to add.</param>
|
|
public void Add (DataColumn column)
|
|
{
|
|
if (column == null)
|
|
throw new ArgumentNullException ("column", "'column' argument cannot be null.");
|
|
|
|
#if !NET_2_0
|
|
/* in 1.1, they must do this here, as the
|
|
* setting of ColumnName below causes an event
|
|
* to be raised */
|
|
column.PropertyChanged += new PropertyChangedEventHandler (ColumnPropertyChanged);
|
|
#endif
|
|
|
|
if (column.ColumnName.Length == 0) {
|
|
column.ColumnName = GetNextDefaultColumnName ();
|
|
}
|
|
|
|
// if (Contains(column.ColumnName))
|
|
// throw new DuplicateNameException("A DataColumn named '" + column.ColumnName + "' already belongs to this DataTable.");
|
|
|
|
if (column.Table != null)
|
|
throw new ArgumentException ("Column '" + column.ColumnName + "' already belongs to this or another DataTable.");
|
|
|
|
column.SetTable (parentTable);
|
|
RegisterName (column.ColumnName, column);
|
|
int ordinal = base.List.Add (column);
|
|
|
|
#if NET_2_0
|
|
column.Ordinal = ordinal;
|
|
#else
|
|
column.SetOrdinal (ordinal);
|
|
#endif
|
|
|
|
// Check if the Column Expression is ok
|
|
if (column.CompiledExpression != null)
|
|
if (parentTable.Rows.Count == 0)
|
|
column.CompiledExpression.Eval (parentTable.NewRow());
|
|
else
|
|
column.CompiledExpression.Eval (parentTable.Rows[0]);
|
|
|
|
// if table already has rows we need to allocate space
|
|
// in the column data container
|
|
if (parentTable.Rows.Count > 0)
|
|
column.DataContainer.Capacity = parentTable.RecordCache.CurrentCapacity;
|
|
|
|
if (column.AutoIncrement) {
|
|
DataRowCollection rows = column.Table.Rows;
|
|
for (int i = 0; i < rows.Count; i++)
|
|
rows [i] [ordinal] = column.AutoIncrementValue ();
|
|
}
|
|
|
|
if (column.AutoIncrement)
|
|
autoIncrement.Add (column);
|
|
|
|
#if NET_2_0
|
|
column.PropertyChanged += new PropertyChangedEventHandler (ColumnPropertyChanged);
|
|
#endif
|
|
|
|
OnCollectionChanged (new CollectionChangeEventArgs(CollectionChangeAction.Add, column));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates and adds a DataColumn object with the specified name to the DataColumnCollection.
|
|
/// </summary>
|
|
/// <param name="columnName">The name of the column.</param>
|
|
/// <returns>The newly created DataColumn.</returns>
|
|
public
|
|
#if !NET_2_0
|
|
virtual
|
|
#endif
|
|
DataColumn Add (string columnName)
|
|
{
|
|
DataColumn column = new DataColumn (columnName);
|
|
Add (column);
|
|
return column;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates and adds a DataColumn object with the specified name and type to the DataColumnCollection.
|
|
/// </summary>
|
|
/// <param name="columnName">The ColumnName to use when cretaing the column.</param>
|
|
/// <param name="type">The DataType of the new column.</param>
|
|
/// <returns>The newly created DataColumn.</returns>
|
|
public
|
|
#if !NET_2_0
|
|
virtual
|
|
#endif
|
|
DataColumn Add (string columnName, Type type)
|
|
{
|
|
if (columnName == null || columnName == "")
|
|
columnName = GetNextDefaultColumnName ();
|
|
|
|
DataColumn column = new DataColumn (columnName, type);
|
|
Add (column);
|
|
return column;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates and adds a DataColumn object with the specified name, type, and expression to the DataColumnCollection.
|
|
/// </summary>
|
|
/// <param name="columnName">The name to use when creating the column.</param>
|
|
/// <param name="type">The DataType of the new column.</param>
|
|
/// <param name="expression">The expression to assign to the Expression property.</param>
|
|
/// <returns>The newly created DataColumn.</returns>
|
|
public
|
|
#if !NET_2_0
|
|
virtual
|
|
#endif
|
|
DataColumn Add (string columnName, Type type, string expression)
|
|
{
|
|
if (columnName == null || columnName == "")
|
|
columnName = GetNextDefaultColumnName ();
|
|
|
|
DataColumn column = new DataColumn (columnName, type, expression);
|
|
Add (column);
|
|
return column;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copies the elements of the specified DataColumn array to the end of the collection.
|
|
/// </summary>
|
|
/// <param name="columns">The array of DataColumn objects to add to the collection.</param>
|
|
public void AddRange (DataColumn [] columns)
|
|
{
|
|
if (parentTable.InitInProgress){
|
|
_mostRecentColumns = columns;
|
|
return;
|
|
}
|
|
|
|
if (columns == null)
|
|
return;
|
|
|
|
foreach (DataColumn column in columns){
|
|
if (column == null)
|
|
continue;
|
|
Add(column);
|
|
}
|
|
}
|
|
|
|
private string GetColumnDependency (DataColumn column)
|
|
{
|
|
|
|
foreach (DataRelation rel in parentTable.ParentRelations)
|
|
if (Array.IndexOf (rel.ChildColumns, column) != -1)
|
|
return String.Format (" child key for relationship {0}.", rel.RelationName);
|
|
foreach (DataRelation rel in parentTable.ChildRelations)
|
|
if (Array.IndexOf (rel.ParentColumns, column) != -1)
|
|
return String.Format (" parent key for relationship {0}.", rel.RelationName);
|
|
|
|
foreach (Constraint c in parentTable.Constraints)
|
|
if (c.IsColumnContained (column))
|
|
return String.Format (" constraint {0} on the table {1}.",
|
|
c.ConstraintName, parentTable);
|
|
|
|
|
|
// check if the foreign-key constraint on any table in the dataset refers to this column.
|
|
// though a forignkeyconstraint automatically creates a uniquecontrainton the parent
|
|
// table and would fail above, but we still need to check, as it is legal to manually remove
|
|
// the constraint on the parent table.
|
|
if (parentTable.DataSet != null)
|
|
foreach (DataTable table in parentTable.DataSet.Tables)
|
|
foreach (Constraint c in table.Constraints)
|
|
if (c is ForeignKeyConstraint && c.IsColumnContained(column))
|
|
return String.Format (
|
|
" constraint {0} on the table {1}.", c.ConstraintName, table.TableName);
|
|
|
|
foreach (DataColumn col in this)
|
|
if (col.CompiledExpression != null && col.CompiledExpression.DependsOn (column))
|
|
return col.Expression;
|
|
return String.Empty;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks whether a given column can be removed from the collection.
|
|
/// </summary>
|
|
/// <param name="column">A DataColumn in the collection.</param>
|
|
/// <returns>true if the column can be removed; otherwise, false.</returns>
|
|
public bool CanRemove (DataColumn column)
|
|
{
|
|
if (column == null || column.Table != parentTable || GetColumnDependency (column) != String.Empty)
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clears the collection of any columns.
|
|
/// </summary>
|
|
public void Clear ()
|
|
{
|
|
CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Refresh, this);
|
|
|
|
// its not necessary to check if each column in the collection can removed.
|
|
// Can simply check, if there are any constraints/relations related to the table,
|
|
// in which case, throw an exception.
|
|
// Also, shudnt check for expression columns since all the columns in the table
|
|
// are being removed.
|
|
if (parentTable.Constraints.Count != 0 ||
|
|
parentTable.ParentRelations.Count != 0 ||
|
|
parentTable.ChildRelations.Count != 0)
|
|
foreach (DataColumn col in this) {
|
|
string s = GetColumnDependency (col);
|
|
if (s != String.Empty)
|
|
throw new ArgumentException ("Cannot remove this column, because it is part of the" + s);
|
|
}
|
|
|
|
if (parentTable.DataSet != null)
|
|
foreach (DataTable table in parentTable.DataSet.Tables)
|
|
foreach (Constraint c in table.Constraints) {
|
|
if (!(c is ForeignKeyConstraint) ||
|
|
((ForeignKeyConstraint) c).RelatedTable != parentTable)
|
|
continue;
|
|
throw new ArgumentException (
|
|
String.Format (
|
|
"Cannot remove this column, because it is part of the constraint {0} on the table {1}",
|
|
c.ConstraintName, table.TableName));
|
|
}
|
|
|
|
foreach (DataColumn col in this)
|
|
col.ResetColumnInfo ();
|
|
|
|
columnFromName.Clear ();
|
|
autoIncrement.Clear ();
|
|
columnNameCount.Clear ();
|
|
base.List.Clear ();
|
|
defaultColumnIndex = 1;
|
|
OnCollectionChanged (e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks whether the collection contains a column with the specified name.
|
|
/// </summary>
|
|
/// <param name="name">The ColumnName of the column to check for.</param>
|
|
/// <returns>true if a column exists with this name; otherwise, false.</returns>
|
|
public bool Contains (string name)
|
|
{
|
|
if (columnFromName.Contains (name))
|
|
return true;
|
|
|
|
return (IndexOf (name, false) != -1);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the index of a column specified by name.
|
|
/// </summary>
|
|
/// <param name="column">The name of the column to return.</param>
|
|
/// <returns>The index of the column specified by column if it is found; otherwise, -1.</returns>
|
|
public
|
|
#if !NET_2_0
|
|
virtual
|
|
#endif
|
|
int IndexOf (DataColumn column)
|
|
{
|
|
if (column == null)
|
|
return -1;
|
|
return base.List.IndexOf (column);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the index of the column with the given name (the name is not case sensitive).
|
|
/// </summary>
|
|
/// <param name="columnName">The name of the column to find.</param>
|
|
/// <returns>The zero-based index of the column with the specified name, or -1 if the column doesn't exist in the collection.</returns>
|
|
public int IndexOf (string columnName)
|
|
{
|
|
if (columnName == null)
|
|
return -1;
|
|
DataColumn dc = columnFromName [columnName] as DataColumn;
|
|
|
|
if (dc != null)
|
|
return IndexOf (dc);
|
|
|
|
return IndexOf (columnName, false);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the OnCollectionChanged event.
|
|
/// </summary>
|
|
/// <param name="ccevent">A CollectionChangeEventArgs that contains the event data.</param>
|
|
#if !NET_2_0
|
|
protected virtual
|
|
#else
|
|
internal
|
|
#endif
|
|
void OnCollectionChanged (CollectionChangeEventArgs ccevent)
|
|
{
|
|
parentTable.ResetPropertyDescriptorsCache ();
|
|
if (CollectionChanged != null)
|
|
CollectionChanged (this, ccevent);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the OnCollectionChanging event.
|
|
/// </summary>
|
|
/// <param name="ccevent">A CollectionChangeEventArgs that contains the event data.</param>
|
|
#if !NET_2_0
|
|
protected internal virtual
|
|
#else
|
|
internal
|
|
#endif
|
|
void OnCollectionChanging (CollectionChangeEventArgs ccevent)
|
|
{
|
|
if (CollectionChanged != null) {
|
|
//FIXME: this is not right
|
|
//CollectionChanged(this, ccevent);
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes the specified DataColumn object from the collection.
|
|
/// </summary>
|
|
/// <param name="column">The DataColumn to remove.</param>
|
|
public void Remove (DataColumn column)
|
|
{
|
|
if (column == null)
|
|
throw new ArgumentNullException ("column", "'column' argument cannot be null.");
|
|
|
|
if (!Contains (column.ColumnName))
|
|
throw new ArgumentException ("Cannot remove a column that doesn't belong to this table.");
|
|
|
|
string dependency = GetColumnDependency (column);
|
|
if (dependency != String.Empty)
|
|
throw new ArgumentException ("Cannot remove this column, because it is part of " + dependency);
|
|
|
|
CollectionChangeEventArgs e = new CollectionChangeEventArgs (CollectionChangeAction.Remove, column);
|
|
|
|
int ordinal = column.Ordinal;
|
|
UnregisterName (column.ColumnName);
|
|
base.List.Remove (column);
|
|
|
|
// Reset column info
|
|
column.ResetColumnInfo ();
|
|
|
|
//Update the ordinals
|
|
for( int i = ordinal ; i < this.Count ; i ++ )
|
|
#if NET_2_0
|
|
this[i].Ordinal = i;
|
|
#else
|
|
this[i].SetOrdinal(i);
|
|
#endif
|
|
|
|
if (parentTable != null)
|
|
parentTable.OnRemoveColumn (column);
|
|
|
|
if (column.AutoIncrement)
|
|
autoIncrement.Remove (column);
|
|
|
|
column.PropertyChanged -= new PropertyChangedEventHandler (ColumnPropertyChanged);
|
|
|
|
OnCollectionChanged (e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes the DataColumn object with the specified name from the collection.
|
|
/// </summary>
|
|
/// <param name="name">The name of the column to remove.</param>
|
|
public void Remove (string name)
|
|
{
|
|
DataColumn column = this [name];
|
|
|
|
if (column == null)
|
|
throw new ArgumentException ("Column '" + name + "' does not belong to table " + ( parentTable == null ? "" : parentTable.TableName ) + ".");
|
|
Remove (column);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes the column at the specified index from the collection.
|
|
/// </summary>
|
|
/// <param name="index">The index of the column to remove.</param>
|
|
public void RemoveAt (int index)
|
|
{
|
|
if (Count <= index)
|
|
throw new IndexOutOfRangeException ("Cannot find column " + index + ".");
|
|
|
|
DataColumn column = this [index];
|
|
Remove (column);
|
|
}
|
|
|
|
// Helper AddRange() - Call this function when EndInit is called
|
|
internal void PostAddRange ()
|
|
{
|
|
if (_mostRecentColumns == null)
|
|
return;
|
|
|
|
foreach (DataColumn column in _mostRecentColumns){
|
|
if (column == null)
|
|
continue;
|
|
Add (column);
|
|
}
|
|
_mostRecentColumns = null;
|
|
}
|
|
|
|
internal void UpdateAutoIncrement (DataColumn col,bool isAutoIncrement)
|
|
{
|
|
if (isAutoIncrement) {
|
|
if (!autoIncrement.Contains (col))
|
|
autoIncrement.Add (col);
|
|
} else {
|
|
if (autoIncrement.Contains (col))
|
|
autoIncrement.Remove (col);
|
|
}
|
|
}
|
|
|
|
private int IndexOf (string name, bool error)
|
|
{
|
|
// exact case matching has already be done by the caller
|
|
// Get existing doublet
|
|
Doublet d = (Doublet) columnNameCount [name];
|
|
if (d != null) {
|
|
if (d.count == 1) {
|
|
// There's only one
|
|
// return index of the column from the only column name of the doublet
|
|
return base.List.IndexOf (columnFromName [d.columnNames [0]]);
|
|
} else if (d.count > 1 && error) {
|
|
// there's more than one, exception!
|
|
throw new ArgumentException ("There is no match for '" + name + "' in the same case and there are multiple matches in different case.");
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
#region Events
|
|
|
|
/// <summary>
|
|
/// Occurs when the columns collection changes, either by adding or removing a column.
|
|
/// </summary>
|
|
[ResDescriptionAttribute ("Occurs whenever this collection's membership changes.")]
|
|
public event CollectionChangeEventHandler CollectionChanged;
|
|
|
|
internal event CollectionChangeEventHandler CollectionMetaDataChanged;
|
|
#endregion
|
|
|
|
private void OnCollectionMetaDataChanged (CollectionChangeEventArgs ccevent)
|
|
{
|
|
parentTable.ResetPropertyDescriptorsCache ();
|
|
if (CollectionMetaDataChanged != null)
|
|
CollectionMetaDataChanged (this, ccevent);
|
|
}
|
|
|
|
private void ColumnPropertyChanged (object sender, PropertyChangedEventArgs args)
|
|
{
|
|
OnCollectionMetaDataChanged (new CollectionChangeEventArgs(CollectionChangeAction.Refresh, sender));
|
|
}
|
|
|
|
#if NET_2_0
|
|
internal void MoveColumn (int oldOrdinal, int newOrdinal)
|
|
{
|
|
if (newOrdinal == -1 || newOrdinal > this.Count)
|
|
throw new ArgumentOutOfRangeException ("ordinal", "Ordinal '" + newOrdinal + "' exceeds the maximum number.");
|
|
if (oldOrdinal == newOrdinal)
|
|
return;
|
|
|
|
int start = newOrdinal > oldOrdinal ? oldOrdinal : newOrdinal;
|
|
int end = newOrdinal > oldOrdinal ? newOrdinal : oldOrdinal;
|
|
int direction = newOrdinal > oldOrdinal ? 1 : (-1);
|
|
|
|
// swap ordinals as per direction of column movement
|
|
if (direction < 0) {
|
|
start = start + end;
|
|
end = start - end;
|
|
start -= end;
|
|
}
|
|
|
|
DataColumn currColumn = this [start];
|
|
for (int i = start; (direction>0 ? i<end : i>end); i += direction) {
|
|
List [i] = List [i+direction];
|
|
((DataColumn) List [i]).Ordinal = i;
|
|
}
|
|
List [end] = currColumn;
|
|
currColumn.Ordinal = end;
|
|
}
|
|
#endif
|
|
}
|
|
}
|