X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem.Data%2FSystem.Data.Common%2FDbDataAdapter.cs;h=9e98ef92d97a5e6efc2cfd8738d734ced793260f;hb=af90548a08ef5effc93b083b7eec44daa178b141;hp=a895a21cc8183bdc54710273329d2ae0a296aebb;hpb=2a8259225695032220537b3c90a99d7a2686f214;p=mono.git diff --git a/mcs/class/System.Data/System.Data.Common/DbDataAdapter.cs b/mcs/class/System.Data/System.Data.Common/DbDataAdapter.cs index a895a21cc81..9e98ef92d97 100644 --- a/mcs/class/System.Data/System.Data.Common/DbDataAdapter.cs +++ b/mcs/class/System.Data/System.Data.Common/DbDataAdapter.cs @@ -40,13 +40,24 @@ using System.Data; using System.Runtime.InteropServices; namespace System.Data.Common { +#if NET_2_0 + public abstract class DbDataAdapter : DataAdapter, IDbDataAdapter, IDataAdapter, ICloneable +#else public abstract class DbDataAdapter : DataAdapter, ICloneable +#endif { #region Fields public const string DefaultSourceTableName = "Table"; const string DefaultSourceColumnName = "Column"; +#if NET_2_0 + IDbCommand _selectCommand; + internal IDbCommand _updateCommand; + internal IDbCommand _deleteCommand; + internal IDbCommand _insertCommand; +#endif + #endregion // Fields #region Constructors @@ -55,7 +66,6 @@ namespace System.Data.Common { { } - [MonoTODO] protected DbDataAdapter(DbDataAdapter adapter) : base(adapter) { } @@ -65,68 +75,84 @@ namespace System.Data.Common { #region Properties #if NET_2_0 - [MonoTODO] - protected virtual IDbConnection BaseConnection { + protected internal CommandBehavior FillCommandBehavior { get { throw new NotImplementedException (); } set { throw new NotImplementedException (); } } - public IDbConnection Connection { - get { return BaseConnection; } - set { BaseConnection = value; } + IDbCommand IDbDataAdapter.SelectCommand { + get { return _selectCommand; } + set { _selectCommand = value; } } -#endif - IDbCommand DeleteCommand { - get { return ((IDbDataAdapter) this).DeleteCommand; } + IDbCommand IDbDataAdapter.UpdateCommand{ + get { return _updateCommand; } + set { _updateCommand = value; } } -#if NET_2_0 - protected internal CommandBehavior FillCommandBehavior { - get { throw new NotImplementedException (); } - set { throw new NotImplementedException (); } + IDbCommand IDbDataAdapter.DeleteCommand{ + get { return _deleteCommand; } + set { _deleteCommand = value; } } -#endif - IDbCommand InsertCommand { - get { return ((IDbDataAdapter) this).InsertCommand; } + IDbCommand IDbDataAdapter.InsertCommand{ + get { return _insertCommand; } + set { _insertCommand = value; } } - -#if NET_2_0 - [MonoTODO] - protected virtual IDbCommand this [[Optional] StatementType statementType] { - get { throw new NotImplementedException (); } - set { throw new NotImplementedException (); } + + [Browsable (false)] + [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] + public DbCommand SelectCommand { + get { return (DbCommand) ((IDbDataAdapter) this).SelectCommand; } + set { ((IDbDataAdapter) this).SelectCommand = value; } } - protected virtual DbProviderFactory ProviderFactory { - get { throw new NotImplementedException (); } + [Browsable (false)] + [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] + public DbCommand DeleteCommand { + get { return (DbCommand) ((IDbDataAdapter) this).DeleteCommand; } + set { ((IDbDataAdapter) this).DeleteCommand = value; } } -#endif - IDbCommand SelectCommand { - get { return ((IDbDataAdapter) this).SelectCommand; } + [Browsable (false)] + [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] + public DbCommand InsertCommand { + get { return (DbCommand) ((IDbDataAdapter) this).InsertCommand; } + set { ((IDbDataAdapter) this).InsertCommand = value; } } -#if NET_2_0 - [MonoTODO] - public IDbTransaction Transaction { - get { throw new NotImplementedException (); } - set { throw new NotImplementedException (); } + [Browsable (false)] + [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] + public DbCommand UpdateCommand { + get { return (DbCommand) ((IDbDataAdapter) this).UpdateCommand; } + set { ((IDbDataAdapter) this).UpdateCommand = value; } } [MonoTODO] - public int UpdateBatchSize { - get { throw new NotImplementedException (); } - set { throw new NotImplementedException (); } + [DefaultValue (1)] + public virtual int UpdateBatchSize { + get { return 1; } + set { throw new NotSupportedException (); } + } +#else + IDbCommand SelectCommand { + get { return ((IDbDataAdapter) this).SelectCommand; } } -#endif IDbCommand UpdateCommand { get { return ((IDbDataAdapter) this).UpdateCommand; } } - #endregion // Properties + IDbCommand DeleteCommand { + get { return ((IDbDataAdapter) this).DeleteCommand; } + } + + IDbCommand InsertCommand { + get { return ((IDbDataAdapter) this).InsertCommand; } + } +#endif + + #endregion // Properties #region Events @@ -142,15 +168,44 @@ namespace System.Data.Common { #region Methods #if NET_2_0 + protected virtual RowUpdatedEventArgs CreateRowUpdatedEvent (DataRow dataRow, IDbCommand command, + StatementType statementType, + DataTableMapping tableMapping) + { + return new RowUpdatedEventArgs (dataRow, command, statementType, tableMapping); + } + + protected virtual RowUpdatingEventArgs CreateRowUpdatingEvent (DataRow dataRow, IDbCommand command, + StatementType statementType, + DataTableMapping tableMapping) + { + return new RowUpdatingEventArgs (dataRow, command, statementType, tableMapping); + } + + [MonoTODO] + protected virtual void OnRowUpdated (RowUpdatedEventArgs value) + { + throw new NotImplementedException (); + } + [MonoTODO] - public virtual void BeginInit () + protected virtual void OnRowUpdating (RowUpdatingEventArgs value) { throw new NotImplementedException (); } +#else + protected abstract RowUpdatedEventArgs CreateRowUpdatedEvent (DataRow dataRow, IDbCommand command, + StatementType statementType, + DataTableMapping tableMapping); + + protected abstract RowUpdatingEventArgs CreateRowUpdatingEvent (DataRow dataRow, IDbCommand command, + StatementType statementType, + DataTableMapping tableMapping); + + protected abstract void OnRowUpdated (RowUpdatedEventArgs value); + protected abstract void OnRowUpdating (RowUpdatingEventArgs value); #endif - protected abstract RowUpdatedEventArgs CreateRowUpdatedEvent (DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping); - protected abstract RowUpdatingEventArgs CreateRowUpdatingEvent (DataRow dataRow, IDbCommand command, StatementType statementType, DataTableMapping tableMapping); private FillErrorEventArgs CreateFillErrorEvent (DataTable dataTable, object[] values, Exception e) { @@ -169,7 +224,7 @@ namespace System.Data.Common { da.SelectCommand = null; } if (da.InsertCommand != null) { - da.InsertCommand.Dispose(); + da.InsertCommand.Dispose(); da.InsertCommand = null; } if (da.UpdateCommand != null) { @@ -183,37 +238,31 @@ namespace System.Data.Common { } } -#if NET_2_0 - [MonoTODO] - public virtual void EndInit () - { - throw new NotImplementedException (); - } -#endif - public override int Fill (DataSet dataSet) { - return Fill (dataSet, 0, 0, DefaultSourceTableName, SelectCommand, CommandBehavior.Default); + return Fill (dataSet, 0, 0, DefaultSourceTableName, ((IDbDataAdapter) this).SelectCommand, CommandBehavior.Default); } public int Fill (DataTable dataTable) { if (dataTable == null) - throw new NullReferenceException (); + throw new ArgumentNullException ("DataTable"); - return Fill (dataTable, SelectCommand, CommandBehavior.Default); + return Fill (dataTable, ((IDbDataAdapter) this).SelectCommand, CommandBehavior.Default); } public int Fill (DataSet dataSet, string srcTable) { - return Fill (dataSet, 0, 0, srcTable, SelectCommand, CommandBehavior.Default); + return Fill (dataSet, 0, 0, srcTable, ((IDbDataAdapter) this).SelectCommand, CommandBehavior.Default); } #if NET_2_0 - protected override int Fill (DataTable dataTable, IDataReader dataReader) + [MonoTODO ("This needs to be moved to DataAdapter.For now, just override")] + protected override #else - protected virtual int Fill (DataTable dataTable, IDataReader dataReader) + protected virtual #endif + int Fill (DataTable dataTable, IDataReader dataReader) { if (dataReader.FieldCount == 0) { dataReader.Close (); @@ -238,6 +287,7 @@ namespace System.Data.Common { protected virtual int Fill (DataTable dataTable, IDbCommand command, CommandBehavior behavior) { CommandBehavior commandBehavior = behavior; + // first see that the connection is not close. if (command.Connection.State == ConnectionState.Closed) { @@ -247,39 +297,43 @@ namespace System.Data.Common { return Fill (dataTable, command.ExecuteReader (commandBehavior)); } + public int Fill (DataSet dataSet, int startRecord, int maxRecords, string srcTable) + { + return this.Fill (dataSet, startRecord, maxRecords, srcTable, ((IDbDataAdapter) this).SelectCommand, CommandBehavior.Default); + } + #if NET_2_0 [MonoTODO] public int Fill (int startRecord, int maxRecords, DataTable[] dataTables) { throw new NotImplementedException (); } -#endif - - public int Fill (DataSet dataSet, int startRecord, int maxRecords, string srcTable) - { - return this.Fill (dataSet, startRecord, maxRecords, srcTable, SelectCommand, CommandBehavior.Default); - } -#if NET_2_0 [MonoTODO] protected virtual int Fill (DataTable[] dataTables, int startRecord, int maxRecords, IDbCommand command, CommandBehavior behavior) { throw new NotImplementedException (); } #endif - + + #if NET_2_0 - protected override int Fill (DataSet dataSet, string srcTable, IDataReader dataReader, int startRecord, int maxRecords) + [MonoTODO ("This needs to be moved to DataAdapter.For now, just override")] + protected override #else - protected virtual int Fill (DataSet dataSet, string srcTable, IDataReader dataReader, int startRecord, int maxRecords) + protected virtual #endif + int Fill (DataSet dataSet, string srcTable, IDataReader dataReader, int startRecord, int maxRecords) { + if (dataSet == null) + throw new ArgumentNullException ("DataSet"); + if (startRecord < 0) throw new ArgumentException ("The startRecord parameter was less than 0."); if (maxRecords < 0) throw new ArgumentException ("The maxRecords parameter was less than 0."); - DataTable dataTable; + DataTable dataTable = null; int resultIndex = 0; int count = 0; @@ -287,18 +341,20 @@ namespace System.Data.Common { string tableName = srcTable; do { // Non-resultset queries like insert, delete or update aren't processed. - if (dataReader.FieldCount != -1) + if (dataReader.FieldCount != -1) { tableName = SetupSchema (SchemaType.Mapped, tableName); if (tableName != null) { - + // check if the table exists in the dataset if (dataSet.Tables.Contains (tableName)) // get the table from the dataset dataTable = dataSet.Tables [tableName]; else { - dataTable = new DataTable(tableName); - dataSet.Tables.Add (dataTable); + // Do not create schema if MissingSchemAction is set to Ignore + if (this.MissingSchemaAction == MissingSchemaAction.Ignore) + continue; + dataTable = dataSet.Tables.Add (tableName); } if (!FillTable (dataTable, dataReader, startRecord, maxRecords, ref count)) { @@ -323,8 +379,9 @@ namespace System.Data.Common { protected virtual int Fill (DataSet dataSet, int startRecord, int maxRecords, string srcTable, IDbCommand command, CommandBehavior behavior) { if (MissingSchemaAction == MissingSchemaAction.AddWithKey) - behavior |= CommandBehavior.KeyInfo; + behavior |= CommandBehavior.KeyInfo; CommandBehavior commandBehavior = behavior; + if (command.Connection.State == ConnectionState.Closed) { command.Connection.Open (); commandBehavior |= CommandBehavior.CloseConnection; @@ -340,7 +397,7 @@ namespace System.Data.Common { int counterStart = counter; int[] mapping = BuildSchema (dataReader, dataTable, SchemaType.Mapped); - + int[] sortedMapping = new int[mapping.Length]; int length = sortedMapping.Length; for(int i=0; i < sortedMapping.Length; i++) { @@ -350,17 +407,16 @@ namespace System.Data.Common { sortedMapping[--length] = i; } - for (int i = 0; i < startRecord; i++) { - dataReader.Read (); - } + for (int i = 0; i < startRecord; i++) { + dataReader.Read (); + } + dataTable.BeginLoadData (); while (dataReader.Read () && (maxRecords == 0 || (counter - counterStart) < maxRecords)) { try { - dataTable.BeginLoadData (); dataTable.LoadDataRow (dataReader, sortedMapping, length, AcceptChangesDuringFill); - dataTable.EndLoadData (); counter++; - } + } catch (Exception e) { object[] readerArray = new object[dataReader.FieldCount]; object[] tableArray = new object[mapping.Length]; @@ -374,20 +430,22 @@ namespace System.Data.Common { } FillErrorEventArgs args = CreateFillErrorEvent (dataTable, tableArray, e); OnFillError (args); - if(!args.Continue) { - return false; - } + + // if args.Continue is not set to true or if a handler is not set, rethrow the error.. + if(!args.Continue) + throw e; } } + dataTable.EndLoadData (); return true; } #if NET_2_0 - /// - /// Fills the given datatable using values from reader. if a value - /// for a column is null, that will be filled with default value. - /// - /// No. of rows affected + /// + /// Fills the given datatable using values from reader. if a value + /// for a column is null, that will be filled with default value. + /// + /// No. of rows affected internal static int FillFromReader (DataTable table, IDataReader reader, int start, @@ -418,26 +476,68 @@ namespace System.Data.Common { return counter; } + internal static int FillFromReader (DataTable table, + IDataReader reader, + int start, + int length, + int [] mapping, + LoadOption loadOption, + FillErrorEventHandler errorHandler) + { + if (reader.FieldCount == 0) + return 0 ; + + for (int i = 0; i < start; i++) + reader.Read (); + + int counter = 0; + object [] values = new object [mapping.Length]; + while (reader.Read () && + (length == 0 || counter < length)) { + + for (int i = 0 ; i < mapping.Length; i++) + values [i] = mapping [i] < 0 ? null : reader [mapping [i]]; + + table.BeginLoadData (); + try { + table.LoadDataRow (values, loadOption); + } catch (Exception e) { + FillErrorEventArgs args = new FillErrorEventArgs (table, values); + args.Errors = e; + args.Continue = false; + errorHandler (table, args); + // if args.Continue is not set to true or if a handler is not set, rethrow the error.. + if(!args.Continue) + throw e; + } + table.EndLoadData (); + counter++; + } + return counter; + } + #endif // NET_2_0 public override DataTable[] FillSchema (DataSet dataSet, SchemaType schemaType) { - return FillSchema (dataSet, schemaType, SelectCommand, DefaultSourceTableName, CommandBehavior.Default); + return FillSchema (dataSet, schemaType, ((IDbDataAdapter) this).SelectCommand, DefaultSourceTableName, CommandBehavior.Default); } public DataTable FillSchema (DataTable dataTable, SchemaType schemaType) { - return FillSchema (dataTable, schemaType, SelectCommand, CommandBehavior.Default); + return FillSchema (dataTable, schemaType, ((IDbDataAdapter) this).SelectCommand, CommandBehavior.Default); } public DataTable[] FillSchema (DataSet dataSet, SchemaType schemaType, string srcTable) { - return FillSchema (dataSet, schemaType, SelectCommand, srcTable, CommandBehavior.Default); + return FillSchema (dataSet, schemaType, ((IDbDataAdapter) this).SelectCommand, srcTable, CommandBehavior.Default); } - [MonoTODO ("Verify")] protected virtual DataTable FillSchema (DataTable dataTable, SchemaType schemaType, IDbCommand command, CommandBehavior behavior) { + if (dataTable == null) + throw new ArgumentNullException ("DataTable"); + behavior |= CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo; if (command.Connection.State == ConnectionState.Closed) { command.Connection.Open (); @@ -450,7 +550,15 @@ namespace System.Data.Common { string tableName = SetupSchema (schemaType, dataTable.TableName); if (tableName != null) { - BuildSchema (reader, dataTable, schemaType); + // FillSchema should add the KeyInfo unless MissingSchemaAction + // is set to Ignore or Error. + MissingSchemaAction schemaAction = MissingSchemaAction; + if (!(schemaAction == MissingSchemaAction.Ignore || + schemaAction == MissingSchemaAction.Error)) + schemaAction = MissingSchemaAction.AddWithKey; + + BuildSchema (reader, dataTable, schemaType, schemaAction, + MissingMappingAction, TableMappings); } } finally @@ -460,9 +568,11 @@ namespace System.Data.Common { return dataTable; } - [MonoTODO ("Verify")] protected virtual DataTable[] FillSchema (DataSet dataSet, SchemaType schemaType, IDbCommand command, string srcTable, CommandBehavior behavior) { + if (dataSet == null) + throw new ArgumentNullException ("DataSet"); + behavior |= CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo; if (command.Connection.State == ConnectionState.Closed) { command.Connection.Open (); @@ -476,20 +586,33 @@ namespace System.Data.Common { DataTable table; try { - tableName = SetupSchema (schemaType, tableName); - if (tableName != null) - { - if (dataSet.Tables.Contains (tableName)) - table = dataSet.Tables [tableName]; - else + // FillSchema should add the KeyInfo unless MissingSchemaAction + // is set to Ignore or Error. + MissingSchemaAction schemaAction = MissingSchemaAction; + if (!(MissingSchemaAction == MissingSchemaAction.Ignore || + MissingSchemaAction == MissingSchemaAction.Error)) + schemaAction = MissingSchemaAction.AddWithKey; + + do { + tableName = SetupSchema (schemaType, tableName); + if (tableName != null) { - table = new DataTable(tableName); - dataSet.Tables.Add (table); + if (dataSet.Tables.Contains (tableName)) + table = dataSet.Tables [tableName]; + else + { + // Do not create schema if MissingSchemAction is set to Ignore + if (this.MissingSchemaAction == MissingSchemaAction.Ignore) + continue; + table = dataSet.Tables.Add (tableName); + } + + BuildSchema (reader, table, schemaType, schemaAction, + MissingMappingAction, TableMappings); + output.Add (table); + tableName = String.Format ("{0}{1}", srcTable, ++index); } - BuildSchema (reader, table, schemaType); - output.Add (table); - tableName = String.Format ("{0}{1}", srcTable, ++index); - } + }while (reader.NextResult ()); } finally { @@ -498,20 +621,6 @@ namespace System.Data.Common { return (DataTable[]) output.ToArray (typeof (DataTable)); } -#if NET_2_0 - [MonoTODO] - public DataSet GetDataSet () - { - throw new NotImplementedException (); - } - - [MonoTODO] - public DataTable GetDataTable () - { - throw new NotImplementedException (); - } -#endif - private string SetupSchema (SchemaType schemaType, string sourceTableName) { DataTableMapping tableMapping = null; @@ -519,7 +628,6 @@ namespace System.Data.Common { if (schemaType == SchemaType.Mapped) { tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction (TableMappings, sourceTableName, sourceTableName, MissingMappingAction); - if (tableMapping != null) return tableMapping.DataSetTable; return null; @@ -531,7 +639,7 @@ namespace System.Data.Common { [EditorBrowsable (EditorBrowsableState.Advanced)] public override IDataParameter[] GetFillParameters () { - IDataParameter[] parameters = new IDataParameter[SelectCommand.Parameters.Count]; + IDataParameter[] parameters = new IDataParameter [SelectCommand.Parameters.Count]; SelectCommand.Parameters.CopyTo (parameters, 0); return parameters; } @@ -540,11 +648,10 @@ namespace System.Data.Common { // "array[ordinal of datatable column] == index of source column in data reader". // each column in the datatable has a mapping to a specific column in the datareader, // the int array represents this match. - [MonoTODO ("Test")] private int[] BuildSchema (IDataReader reader, DataTable table, SchemaType schemaType) { - return BuildSchema (reader, table, schemaType, MissingSchemaAction, - MissingMappingAction, TableMappings); + return BuildSchema (reader, table, schemaType, MissingSchemaAction, + MissingMappingAction, TableMappings); } /// @@ -558,7 +665,7 @@ namespace System.Data.Common { MissingMappingAction missingMapAction, DataTableMappingCollection dtMapping ) - { + { int readerIndex = 0; // FIXME : this fails if query has fewer columns than a table int[] mapping = new int[table.Columns.Count]; // mapping the reader indexes to the datatable indexes @@ -570,16 +677,30 @@ namespace System.Data.Common { ArrayList primaryKey = new ArrayList (); ArrayList sourceColumns = new ArrayList (); bool createPrimaryKey = true; - - foreach (DataRow schemaRow in reader.GetSchemaTable ().Rows) { + + DataTable schemaTable = reader.GetSchemaTable (); + + DataColumn ColumnNameCol = schemaTable.Columns["ColumnName"]; + DataColumn DataTypeCol = schemaTable.Columns["DataType"]; + DataColumn IsAutoIncrementCol = schemaTable.Columns["IsAutoIncrement"]; + DataColumn AllowDBNullCol = schemaTable.Columns["AllowDBNull"]; + DataColumn IsReadOnlyCol = schemaTable.Columns["IsReadOnly"]; + DataColumn IsKeyCol = schemaTable.Columns["IsKey"]; + DataColumn IsUniqueCol = schemaTable.Columns["IsUnique"]; + DataColumn ColumnSizeCol = schemaTable.Columns["ColumnSize"]; + + foreach (DataRow schemaRow in schemaTable.Rows) { // generate a unique column name in the source table. string sourceColumnName; - if (schemaRow.IsNull("ColumnName")) + string realSourceColumnName ; + if (ColumnNameCol == null || schemaRow.IsNull(ColumnNameCol) || (string)schemaRow [ColumnNameCol] == String.Empty) { sourceColumnName = DefaultSourceColumnName; - else - sourceColumnName = (string) schemaRow ["ColumnName"]; - - string realSourceColumnName = sourceColumnName; + realSourceColumnName = DefaultSourceColumnName + "1"; + } + else { + sourceColumnName = (string) schemaRow [ColumnNameCol]; + realSourceColumnName = sourceColumnName; + } for (int i = 1; sourceColumns.Contains (realSourceColumnName); i += 1) realSourceColumnName = String.Format ("{0}{1}", sourceColumnName, i); @@ -588,21 +709,24 @@ namespace System.Data.Common { // generate DataSetColumnName from DataTableMapping, if any string dsColumnName = realSourceColumnName; DataTableMapping tableMapping = null; - tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction (dtMapping, table.TableName, table.TableName, missingMapAction); - if (tableMapping != null) + + //FIXME : The sourcetable name shud get passed as a parameter.. + int index = dtMapping.IndexOfDataSetTable (table.TableName); + string srcTable = (index != -1 ? dtMapping[index].SourceTable : table.TableName); + tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction (dtMapping, srcTable, table.TableName, missingMapAction); + if (tableMapping != null) { - table.TableName = tableMapping.DataSetTable; // check to see if the column mapping exists DataColumnMapping columnMapping = DataColumnMappingCollection.GetColumnMappingBySchemaAction(tableMapping.ColumnMappings, realSourceColumnName, missingMapAction); if (columnMapping != null) { - Type columnType = (Type)schemaRow["DataType"]; + Type columnType = (Type)schemaRow[DataTypeCol]; DataColumn col = columnMapping.GetDataColumnBySchemaAction( - table , - columnType, - missingSchAction); + table , + columnType, + missingSchAction); if (col != null) { @@ -610,7 +734,7 @@ namespace System.Data.Common { if (table.Columns.IndexOf(col) == -1) { if (missingSchAction == MissingSchemaAction.Add - || missingSchAction == MissingSchemaAction.AddWithKey) + || missingSchAction == MissingSchemaAction.AddWithKey) table.Columns.Add(col); int[] tmp = new int[mapping.Length + 1]; @@ -618,13 +742,26 @@ namespace System.Data.Common { Array.Copy(mapping,col.Ordinal,tmp,col.Ordinal + 1,mapping.Length - col.Ordinal); mapping = tmp; } - bool isAutoIncrement = (bool)schemaRow["IsAutoIncrement"]; - bool allowDBNull = (bool)schemaRow["AllowDBNull"]; - bool isReadOnly =(bool)schemaRow["IsReadOnly"]; - bool isKey = (bool)schemaRow["IsKey"]; - bool isUnique = (bool)schemaRow["IsUnique"]; - if (missingSchAction == MissingSchemaAction.AddWithKey) { + + if (missingSchAction == MissingSchemaAction.AddWithKey) { + + object value = (AllowDBNullCol != null) ? schemaRow[AllowDBNullCol] : null; + bool allowDBNull = value is bool ? (bool)value : true; + + value = (IsKeyCol != null) ? schemaRow[IsKeyCol] : null; + bool isKey = value is bool ? (bool)value : false; + + value = (IsAutoIncrementCol != null) ? schemaRow[IsAutoIncrementCol] : null; + bool isAutoIncrement = value is bool ? (bool)value : false; + + value = (IsReadOnlyCol != null) ? schemaRow[IsReadOnlyCol] : null; + bool isReadOnly = value is bool ? (bool)value : false; + + value = (IsUniqueCol != null) ? schemaRow[IsUniqueCol] : null; + bool isUnique = value is bool ? (bool)value : false; + + col.AllowDBNull = allowDBNull; // fill woth key info if (isAutoIncrement && DataColumn.CanAutoIncrement(columnType)) { col.AutoIncrement = true; @@ -633,27 +770,33 @@ namespace System.Data.Common { } if (columnType == DbTypes.TypeOfString) { - col.MaxLength = (int)schemaRow["ColumnSize"]; + col.MaxLength = (ColumnSizeCol != null) ? (int)schemaRow[ColumnSizeCol] : 0; } if (isReadOnly) col.ReadOnly = true; - } - - if (!allowDBNull && (!isReadOnly || isKey)) - col.AllowDBNull = false; - if (isUnique && !isKey && !columnType.IsArray) { - col.Unique = true; - if (!allowDBNull) + + if (!allowDBNull && (!isReadOnly || isKey)) col.AllowDBNull = false; - } + if (isUnique && !isKey && !columnType.IsArray) { + col.Unique = true; + if (!allowDBNull) + col.AllowDBNull = false; + } + + // This might not be set by all DataProviders + bool isHidden = false; + if (schemaTable.Columns.Contains ("IsHidden")) { + value = schemaRow["IsHidden"]; + isHidden = ((value is bool) ? (bool)value : false); + } - if (isKey) { - primaryKey.Add (col); - if (allowDBNull) - createPrimaryKey = false; - } - + if (isKey && !isHidden) { + primaryKey.Add (col); + if (allowDBNull) + createPrimaryKey = false; + } + } // add the ordinal of the column as a key and the index of the column in the datareader as a value. mapping[col.Ordinal] = readerIndex++; } @@ -677,9 +820,7 @@ namespace System.Data.Common { table.Constraints.Add(uConstraint); } } - return mapping; - } [MonoTODO] @@ -688,7 +829,6 @@ namespace System.Data.Common { throw new NotImplementedException (); } - [MonoTODO] public int Update (DataRow[] dataRows) { if (dataRows == null) @@ -711,9 +851,9 @@ namespace System.Data.Common { throw new ArgumentException("dataRows[" + i + "]."); if (dataRows[i].Table != table) throw new ArgumentException( - " DataRow[" - + i - + "] is from a different DataTable than DataRow[0]."); + " DataRow[" + + i + + "] is from a different DataTable than DataRow[0]."); } // get table mapping for this rows @@ -721,10 +861,10 @@ namespace System.Data.Common { if (tableMapping == null) { tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction( - TableMappings, - table.TableName, - table.TableName, - MissingMappingAction); + TableMappings, + table.TableName, + table.TableName, + MissingMappingAction); if (tableMapping != null) { foreach (DataColumn col in table.Columns) { if (tableMapping.ColumnMappings.IndexOf (col.ColumnName) >= 0) @@ -740,9 +880,9 @@ namespace System.Data.Common { cmc.Add (new DataColumnMapping (col.ColumnName, col.ColumnName)); tableMapping = new DataTableMapping ( - table.TableName, - table.TableName, - cmc.ToArray (typeof (DataColumnMapping)) as DataColumnMapping []); + table.TableName, + table.TableName, + cmc.ToArray (typeof (DataColumnMapping)) as DataColumnMapping []); } } @@ -758,20 +898,20 @@ namespace System.Data.Common { public int Update (DataTable dataTable) { - /* - int index = TableMappings.IndexOfDataSetTable (dataTable.TableName); - if (index < 0) - throw new ArgumentException (); - return Update (dataTable, TableMappings [index]); - */ + /* + int index = TableMappings.IndexOfDataSetTable (dataTable.TableName); + if (index < 0) + throw new ArgumentException (); + return Update (dataTable, TableMappings [index]); + */ DataTableMapping tableMapping = TableMappings.GetByDataSetTable (dataTable.TableName); if (tableMapping == null) { tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction ( - TableMappings, - dataTable.TableName, - dataTable.TableName, - MissingMappingAction); + TableMappings, + dataTable.TableName, + dataTable.TableName, + MissingMappingAction); if (tableMapping != null) { foreach (DataColumn col in dataTable.Columns) { if (tableMapping.ColumnMappings.IndexOf (col.ColumnName) >= 0) @@ -787,9 +927,9 @@ namespace System.Data.Common { cmc.Add (new DataColumnMapping (col.ColumnName, col.ColumnName)); tableMapping = new DataTableMapping ( - dataTable.TableName, - dataTable.TableName, - cmc.ToArray (typeof (DataColumnMapping)) as DataColumnMapping []); + dataTable.TableName, + dataTable.TableName, + cmc.ToArray (typeof (DataColumnMapping)) as DataColumnMapping []); } } return Update (dataTable, tableMapping); @@ -802,7 +942,6 @@ namespace System.Data.Common { return Update (rows, tableMapping); } - [MonoTODO] protected virtual int Update (DataRow[] dataRows, DataTableMapping tableMapping) { int updateCount = 0; @@ -814,17 +953,17 @@ namespace System.Data.Common { switch (row.RowState) { case DataRowState.Added: statementType = StatementType.Insert; - command = InsertCommand; + command = ((IDbDataAdapter) this).InsertCommand; commandName = "Insert"; break; case DataRowState.Deleted: statementType = StatementType.Delete; - command = DeleteCommand; + command = ((IDbDataAdapter) this).DeleteCommand; commandName = "Delete"; break; case DataRowState.Modified: statementType = StatementType.Update; - command = UpdateCommand; + command = ((IDbDataAdapter) this).UpdateCommand; commandName = "Update"; break; case DataRowState.Unchanged: @@ -834,25 +973,54 @@ namespace System.Data.Common { RowUpdatingEventArgs argsUpdating = CreateRowUpdatingEvent (row, command, statementType, tableMapping); row.RowError = null; + OnRowUpdating(argsUpdating); + switch(argsUpdating.Status) { + case UpdateStatus.Continue : + //continue in update operation + break; + case UpdateStatus.ErrorsOccurred : + if (argsUpdating.Errors == null) { + argsUpdating.Errors = ExceptionHelper.RowUpdatedError(); + } + row.RowError += argsUpdating.Errors.Message; + if (!ContinueUpdateOnError) { + throw argsUpdating.Errors; + } + continue; + case UpdateStatus.SkipAllRemainingRows : + return updateCount; + case UpdateStatus.SkipCurrentRow : + updateCount++; + continue; + default : + throw ExceptionHelper.InvalidUpdateStatus(argsUpdating.Status); + } + command = argsUpdating.Command; try { if (command != null) { DataColumnMappingCollection columnMappings = tableMapping.ColumnMappings; + IDataParameter nullCheckParam = null; foreach (IDataParameter parameter in command.Parameters) { if ((parameter.Direction & ParameterDirection.Input) != 0) { string dsColumnName = parameter.SourceColumn; if (columnMappings.Contains(parameter.SourceColumn)) dsColumnName = columnMappings [parameter.SourceColumn].DataSetColumn; - if (dsColumnName == null || dsColumnName.Length <= 0) - continue; - DataRowVersion rowVersion = DataRowVersion.Default; + if (dsColumnName == null || dsColumnName.Length <= 0) { + nullCheckParam = parameter; + continue; + } + DataRowVersion rowVersion = parameter.SourceVersion; // Parameter version is ignored for non-update commands - if (statementType == StatementType.Update) - rowVersion = parameter.SourceVersion; if (statementType == StatementType.Delete) rowVersion = DataRowVersion.Original; parameter.Value = row [dsColumnName, rowVersion]; + if (nullCheckParam != null && (parameter.Value != null + && parameter.Value != DBNull.Value)) { + nullCheckParam.Value = 0; + nullCheckParam = null; + } } } } @@ -862,39 +1030,15 @@ namespace System.Data.Common { argsUpdating.Status = UpdateStatus.ErrorsOccurred; } - OnRowUpdating(argsUpdating); - - switch(argsUpdating.Status) { - case UpdateStatus.Continue : - //continue in update operation - break; - case UpdateStatus.ErrorsOccurred : - if (argsUpdating.Errors == null) { - argsUpdating.Errors = new DataException("RowUpdatedEvent: Errors occurred; no additional is information available."); - } - row.RowError += argsUpdating.Errors.Message; - if (!ContinueUpdateOnError) { - throw argsUpdating.Errors; - } - continue; - case UpdateStatus.SkipAllRemainingRows : - return updateCount; - case UpdateStatus.SkipCurrentRow : - updateCount++; - continue; - default : - throw new ArgumentException(String.Format("Invalid UpdateStatus: {0}",argsUpdating.Status)); - } - - command = argsUpdating.Command; + IDataReader reader = null; try { if (command == null) { - throw new InvalidOperationException("ADP_UpdateRequiresCommand" + command); + throw ExceptionHelper.UpdateRequiresCommand(commandName); } CommandBehavior commandBehavior = CommandBehavior.Default; - if (command.Connection.State == ConnectionState.Closed) { + if (command.Connection.State == ConnectionState.Closed) { command.Connection.Open (); commandBehavior |= CommandBehavior.CloseConnection; } @@ -903,105 +1047,107 @@ namespace System.Data.Common { // so the connection will be closed if needed. reader = command.ExecuteReader (commandBehavior); - // update the current row, if the update command returns any resultset - // ignore other than the first record. - DataColumnMappingCollection columnMappings = tableMapping.ColumnMappings; - - if (command.UpdatedRowSource == UpdateRowSource.Both || - command.UpdatedRowSource == UpdateRowSource.FirstReturnedRecord) { - if (reader.Read ()){ - DataTable retSchema = reader.GetSchemaTable (); - foreach (DataRow dr in retSchema.Rows) { - string columnName = dr ["ColumnName"].ToString (); - string dstColumnName = columnName; - if (columnMappings != null && - columnMappings.Contains(columnName)) - dstColumnName = columnMappings [dstColumnName].DataSetColumn; - DataColumn dstColumn = row.Table.Columns [dstColumnName]; - if (dstColumn == null - || (dstColumn.Expression != null - && dstColumn.Expression.Length > 0)) - continue; - // info from : http://www.error-bank.com/microsoft.public.dotnet.framework.windowsforms.databinding/ - // _35_hcsyiv0dha.2328@tk2msftngp10.phx.gbl_Thread.aspx - // disable readonly for non-expression columns. - bool readOnlyState = dstColumn.ReadOnly; - dstColumn.ReadOnly = false; - try { - row [dstColumnName] = reader [columnName]; - } finally { - dstColumn.ReadOnly = readOnlyState; - } - } - } - } - reader.Close (); - - int tmp = reader.RecordsAffected; // records affected is valid only after closing reader + // update the current row, if the update command returns any resultset + // ignore other than the first record. + DataColumnMappingCollection columnMappings = tableMapping.ColumnMappings; + + if (command.UpdatedRowSource == UpdateRowSource.Both || + command.UpdatedRowSource == UpdateRowSource.FirstReturnedRecord) { + if (reader.Read ()){ + DataTable retSchema = reader.GetSchemaTable (); + foreach (DataRow dr in retSchema.Rows) { + string columnName = dr ["ColumnName"].ToString (); + string dstColumnName = columnName; + if (columnMappings != null && + columnMappings.Contains(columnName)) + dstColumnName = columnMappings [dstColumnName].DataSetColumn; + DataColumn dstColumn = row.Table.Columns [dstColumnName]; + if (dstColumn == null + || (dstColumn.Expression != null + && dstColumn.Expression.Length > 0)) + continue; + // info from : http://www.error-bank.com/microsoft.public.dotnet.framework.windowsforms.databinding/ + // _35_hcsyiv0dha.2328@tk2msftngp10.phx.gbl_Thread.aspx + // disable readonly for non-expression columns. + bool readOnlyState = dstColumn.ReadOnly; + dstColumn.ReadOnly = false; + try { + row [dstColumnName] = reader [columnName]; + } finally { + dstColumn.ReadOnly = readOnlyState; + } + } + } + } + reader.Close (); + + int tmp = reader.RecordsAffected; // records affected is valid only after closing reader // if the execute does not effect any rows we throw an exception. if (tmp == 0) throw new DBConcurrencyException("Concurrency violation: the " + commandName +"Command affected 0 records."); updateCount += tmp; - if (command.UpdatedRowSource == UpdateRowSource.Both || - command.UpdatedRowSource == UpdateRowSource.OutputParameters) { - // Update output parameters to row values - foreach (IDataParameter parameter in command.Parameters) { - if (parameter.Direction != ParameterDirection.InputOutput - && parameter.Direction != ParameterDirection.Output - && parameter.Direction != ParameterDirection.ReturnValue) - continue; - - string dsColumnName = parameter.SourceColumn; - if (columnMappings != null && - columnMappings.Contains(parameter.SourceColumn)) - dsColumnName = columnMappings [parameter.SourceColumn].DataSetColumn; - DataColumn dstColumn = row.Table.Columns [dsColumnName]; - if (dstColumn == null - || (dstColumn.Expression != null - && dstColumn.Expression.Length > 0)) - continue; - bool readOnlyState = dstColumn.ReadOnly; - dstColumn.ReadOnly = false; - try { - row [dsColumnName] = parameter.Value; - } finally { - dstColumn.ReadOnly = readOnlyState; - } + if (command.UpdatedRowSource == UpdateRowSource.Both || + command.UpdatedRowSource == UpdateRowSource.OutputParameters) { + // Update output parameters to row values + foreach (IDataParameter parameter in command.Parameters) { + if (parameter.Direction != ParameterDirection.InputOutput + && parameter.Direction != ParameterDirection.Output + && parameter.Direction != ParameterDirection.ReturnValue) + continue; + + string dsColumnName = parameter.SourceColumn; + if (columnMappings != null && + columnMappings.Contains(parameter.SourceColumn)) + dsColumnName = columnMappings [parameter.SourceColumn].DataSetColumn; + DataColumn dstColumn = row.Table.Columns [dsColumnName]; + if (dstColumn == null + || (dstColumn.Expression != null + && dstColumn.Expression.Length > 0)) + continue; + bool readOnlyState = dstColumn.ReadOnly; + dstColumn.ReadOnly = false; + try { + row [dsColumnName] = parameter.Value; + } finally { + dstColumn.ReadOnly = readOnlyState; + } - } - } + } + } - RowUpdatedEventArgs updatedArgs = CreateRowUpdatedEvent(row, command, statementType, tableMapping); - OnRowUpdated(updatedArgs); - switch(updatedArgs.Status) { - case UpdateStatus.Continue: - break; - case UpdateStatus.ErrorsOccurred: - if (updatedArgs.Errors == null) { - updatedArgs.Errors = new DataException("RowUpdatedEvent: Errors occurred; no additional is information available."); - } - row.RowError += updatedArgs.Errors.Message; - if (!ContinueUpdateOnError) { - throw updatedArgs.Errors; - } - break; - case UpdateStatus.SkipCurrentRow: - continue; - case UpdateStatus.SkipAllRemainingRows: - return updateCount; - } + RowUpdatedEventArgs updatedArgs = CreateRowUpdatedEvent(row, command, statementType, tableMapping); + OnRowUpdated(updatedArgs); + switch(updatedArgs.Status) { + case UpdateStatus.Continue: + break; + case UpdateStatus.ErrorsOccurred: + if (updatedArgs.Errors == null) { + updatedArgs.Errors = ExceptionHelper.RowUpdatedError(); + } + row.RowError += updatedArgs.Errors.Message; + if (!ContinueUpdateOnError) { + throw updatedArgs.Errors; + } + break; + case UpdateStatus.SkipCurrentRow: + continue; + case UpdateStatus.SkipAllRemainingRows: + return updateCount; + } +#if NET_2_0 + if (!AcceptChangesDuringUpdate) + continue; +#endif row.AcceptChanges (); - } - catch(Exception e) { + } catch(Exception e) { row.RowError = e.Message; if (!ContinueUpdateOnError) { throw e; } - } - finally { - if (reader != null) { + } finally { + if (reader != null && ! reader.IsClosed) { reader.Close (); } } @@ -1012,16 +1158,53 @@ namespace System.Data.Common { public int Update (DataSet dataSet, string sourceTable) { MissingMappingAction mappingAction = MissingMappingAction; + if (mappingAction == MissingMappingAction.Ignore) mappingAction = MissingMappingAction.Error; + DataTableMapping tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction (TableMappings, sourceTable, sourceTable, mappingAction); DataTable dataTable = dataSet.Tables[tableMapping.DataSetTable]; if (dataTable == null) - throw new ArgumentException ("sourceTable"); - + throw new ArgumentException (String.Format ("Missing table {0}", + sourceTable)); return Update (dataTable, tableMapping); } + +#if NET_2_0 + // All the batch methods, should be implemented, if supported, + // by individual providers + + protected virtual int AddToBatch (IDbCommand cmd) + { + throw new NotSupportedException (); + } + + protected virtual void ClearBatch () + { + throw new NotSupportedException (); + } + + protected virtual int ExecuteBatch () + { + throw new NotSupportedException (); + } + + protected virtual IDataParameter GetBatchedParameter (int commandIdentifier, int parameterIdentifer) + { + throw new NotSupportedException (); + } + + protected virtual void InitializeBatching () + { + throw new NotSupportedException (); + } + + protected virtual void TerminateBatching () + { + throw new NotSupportedException (); + } +#endif #if ONLY_1_0 || ONLY_1_1 protected virtual void OnFillError (FillErrorEventArgs value) @@ -1031,9 +1214,6 @@ namespace System.Data.Common { } #endif - protected abstract void OnRowUpdated (RowUpdatedEventArgs value); - protected abstract void OnRowUpdating (RowUpdatingEventArgs value); - #endregion // Methods } }