diff options
-rw-r--r-- | mcs/class/System.Data/System.Data.Common/DbDataAdapter.cs | 363 |
1 files changed, 253 insertions, 110 deletions
diff --git a/mcs/class/System.Data/System.Data.Common/DbDataAdapter.cs b/mcs/class/System.Data/System.Data.Common/DbDataAdapter.cs index d6344939751..1b5de338d06 100644 --- a/mcs/class/System.Data/System.Data.Common/DbDataAdapter.cs +++ b/mcs/class/System.Data/System.Data.Common/DbDataAdapter.cs @@ -111,26 +111,46 @@ namespace System.Data.Common { dataReader.Close (); return 0; } - - object[] itemArray = new object [dataReader.FieldCount]; - SetupSchema (SchemaType.Mapped, dataTable.TableName, dataTable); // FIXME - BuildSchema (dataReader, dataTable, SchemaType.Mapped); - - while (doContinue && dataReader.Read ()) { - dataReader.GetValues (itemArray); - try { - dataTable.BeginLoadData (); - dataTable.LoadDataRow (itemArray, AcceptChangesDuringFill); - dataTable.EndLoadData (); - count += 1; - } - catch (Exception e) { - FillErrorEventArgs args = CreateFillErrorEvent (dataTable, itemArray, e); - OnFillError (args); - doContinue = args.Continue; + + try + { + object[] itemArray = new object [dataReader.FieldCount]; + string tableName = SetupSchema (SchemaType.Mapped, dataTable.TableName); + if (tableName != null) + { + dataTable.TableName = tableName; + Hashtable mapping = BuildSchema (dataReader, dataTable, SchemaType.Mapped); + + while (doContinue && dataReader.Read ()) + { + // we get the values from the datareader + dataReader.GetValues (itemArray); + + // we only need the values that has a mapping to the table. + object[] tableArray = new object[mapping.Count]; + for (int i = 0; i < tableArray.Length; i++) + tableArray[i] = mapping[i]; // get the value for each column + + try + { + dataTable.BeginLoadData (); + dataTable.LoadDataRow (itemArray, AcceptChangesDuringFill); + dataTable.EndLoadData (); + count += 1; + } + catch (Exception e) + { + FillErrorEventArgs args = CreateFillErrorEvent (dataTable, itemArray, e); + OnFillError (args); + doContinue = args.Continue; + } + } } } - dataReader.Close (); + finally + { + dataReader.Close (); + } return count; } @@ -168,53 +188,76 @@ namespace System.Data.Common { int resultIndex = 0; int count = 0; bool doContinue = true; - - string tableName = srcTable; - object[] itemArray = new object [dataReader.FieldCount]; - - do { - dataTable = new DataTable (); - SetupSchema (SchemaType.Mapped, tableName, dataTable); - - // check if the table exists in the dataset - if (dataSet.Tables.Contains (dataTable.TableName)) - // get the table from the dataset - dataTable = dataSet.Tables [dataTable.TableName]; - else - dataSet.Tables.Add (dataTable); - BuildSchema (dataReader, dataTable, SchemaType.Mapped); - - for (int i = 0; i < startRecord; i += 1) - dataReader.Read (); - - while (doContinue && dataReader.Read () && !(maxRecords > 0 && count >= maxRecords)) { - dataReader.GetValues (itemArray); - try { - dataTable.BeginLoadData (); - dataTable.LoadDataRow (itemArray, AcceptChangesDuringFill); - dataTable.EndLoadData (); - count += 1; - } - catch (Exception e) { - FillErrorEventArgs args = CreateFillErrorEvent (dataTable, itemArray, e); - OnFillError (args); - doContinue = args.Continue; + + try + { + string tableName = srcTable; + object[] itemArray; + + do + { + 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); + } + Hashtable mapping = BuildSchema (dataReader, dataTable, SchemaType.Mapped); + + for (int i = 0; i < startRecord; i += 1) + dataReader.Read (); + + itemArray = new object [dataReader.FieldCount]; + + while (doContinue && dataReader.Read () && !(maxRecords > 0 && count >= maxRecords)) + { + // we get the values from the datareader + dataReader.GetValues (itemArray); + + // we only need the values that has a mapping to the table. + object[] tableArray = new object[mapping.Count]; + for (int i = 0; i < tableArray.Length; i++) + tableArray[i] = itemArray[(int)mapping[i]]; // get the value for each column + + try + { + dataTable.BeginLoadData (); + //dataTable.LoadDataRow (itemArray, AcceptChangesDuringFill); + dataTable.LoadDataRow (tableArray, AcceptChangesDuringFill); + dataTable.EndLoadData (); + count += 1; + } + catch (Exception e) + { + FillErrorEventArgs args = CreateFillErrorEvent (dataTable, itemArray, e); + OnFillError (args); + doContinue = args.Continue; + } + } + + tableName = String.Format ("{0}{1}", srcTable, ++resultIndex); + + startRecord = 0; + maxRecords = 0; } - } - - tableName = String.Format ("{0}{1}", srcTable, ++resultIndex); - startRecord = 0; - maxRecords = 0; - - } while (doContinue && dataReader.NextResult ()); - - dataReader.Close (); + } while (doContinue && dataReader.NextResult ()); + } + finally + { + dataReader.Close (); + } return count; } - + protected virtual int Fill (DataSet dataSet, int startRecord, int maxRecords, string srcTable, IDbCommand command, CommandBehavior behavior) { CommandBehavior commandBehavior = behavior; @@ -243,7 +286,6 @@ namespace System.Data.Common { [MonoTODO ("Verify")] protected virtual DataTable FillSchema (DataTable dataTable, SchemaType schemaType, IDbCommand command, CommandBehavior behavior) { - DataTable table; behavior |= CommandBehavior.SchemaOnly | CommandBehavior.KeyInfo; if (command.Connection.State == ConnectionState.Closed) { command.Connection.Open (); @@ -251,12 +293,19 @@ namespace System.Data.Common { } IDataReader reader = command.ExecuteReader (behavior); - table = new DataTable (); - SetupSchema (schemaType, DefaultSourceTableName, table); - BuildSchema (reader, table, schemaType); - - reader.Close (); - return table; + try + { + string tableName = SetupSchema (schemaType, dataTable.TableName); + if (tableName != null) + { + BuildSchema (reader, dataTable, schemaType); + } + } + finally + { + reader.Close (); + } + return dataTable; } [MonoTODO ("Verify")] @@ -272,47 +321,65 @@ namespace System.Data.Common { ArrayList output = new ArrayList (); string tableName = srcTable; int index = 0; - - do { - // FixMe: Allocate table only if it doesn't exist already! - DataTable table = new DataTable (); - SetupSchema (schemaType, tableName, table); - if (dataSet.Tables.Contains (table.TableName)) - table = dataSet.Tables [table.TableName]; - else - dataSet.Tables.Add (table); - BuildSchema (reader, table, schemaType); - output.Add (table); - tableName = String.Format ("{0}{1}", srcTable, ++index); - } while (reader.NextResult ()); - reader.Close (); + DataTable table; + try + { + tableName = SetupSchema (schemaType, tableName); + if (tableName != null) + { + if (dataSet.Tables.Contains (tableName)) + table = dataSet.Tables [tableName]; + else + { + table = new DataTable(tableName); + dataSet.Tables.Add (table); + } + BuildSchema (reader, table, schemaType); + output.Add (table); + tableName = String.Format ("{0}{1}", srcTable, ++index); + } + } + finally + { + reader.Close (); + } return (DataTable[]) output.ToArray (typeof (DataTable)); } - private void SetupSchema (SchemaType schemaType, string sourceTableName, DataTable table) + private string SetupSchema (SchemaType schemaType, string sourceTableName) { DataTableMapping tableMapping = null; if (schemaType == SchemaType.Mapped) - tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction (TableMappings, sourceTableName, "", MissingMappingAction.Ignore); + { + tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction (TableMappings, sourceTableName, sourceTableName, MissingMappingAction); - if (tableMapping != null) - table.TableName = tableMapping.DataSetTable; + if (tableMapping != null) + return tableMapping.DataSetTable; + return null; + } else - table.TableName = sourceTableName; + return sourceTableName; } [EditorBrowsable (EditorBrowsableState.Advanced)] public override IDataParameter[] GetFillParameters () { - object[] parameters = new object [SelectCommand.Parameters.Count]; + IDataParameter[] parameters = new IDataParameter[SelectCommand.Parameters.Count]; SelectCommand.Parameters.CopyTo (parameters, 0); - return (IDataParameter[]) parameters; + return parameters; } - + + // this method bulds the schema for a given datatable + // returns a hashtable that his keys are the ordinal of the datatable columns, and his values + // are the indexes of the source columns in the data reader. + // each column in the datatable has a mapping to a specific column in the datareader + // the hashtable represents this match. [MonoTODO ("Test")] - private void BuildSchema (IDataReader reader, DataTable table, SchemaType schemaType) + private Hashtable BuildSchema (IDataReader reader, DataTable table, SchemaType schemaType) { + int readerIndex = 0; + Hashtable mapping = new Hashtable(); // hashing the reader indexes with the datatable indexes ArrayList primaryKey = new ArrayList (); ArrayList sourceColumns = new ArrayList (); @@ -334,31 +401,45 @@ namespace System.Data.Common { string dsColumnName = realSourceColumnName; DataTableMapping tableMapping = null; if (schemaType == SchemaType.Mapped) - tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction (TableMappings, table.TableName, table.TableName, MissingMappingAction.Ignore); - if (tableMapping != null) { + tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction (TableMappings, table.TableName, table.TableName, MissingMappingAction); + if (tableMapping != null) + { + table.TableName = tableMapping.DataSetTable; - // check to see if the column mapping exists - if (tableMapping.ColumnMappings.Contains (dsColumnName)) { - dsColumnName = tableMapping.ColumnMappings [realSourceColumnName].DataSetColumn; - } else { - if (MissingSchemaAction == MissingSchemaAction.Error) - throw new SystemException (); - tableMapping.ColumnMappings.Add (sourceColumnName, dsColumnName); + DataColumnMapping columnMapping = DataColumnMappingCollection.GetColumnMappingBySchemaAction(tableMapping.ColumnMappings, realSourceColumnName, MissingMappingAction); + if (columnMapping != null) + { + DataColumn col = + columnMapping.GetDataColumnBySchemaAction( + table , + (Type)schemaRow["DataType"], + MissingSchemaAction); + + if (col != null) + { + // if the column is not in the table - add it. + if (table.Columns.IndexOf(col) == -1) + { + if (MissingSchemaAction == MissingSchemaAction.Add || MissingSchemaAction == MissingSchemaAction.AddWithKey) + table.Columns.Add(col); + } + + if (!schemaRow["IsKey"].Equals (DBNull.Value)) + if ((bool) (schemaRow ["IsKey"])) + primaryKey.Add (col); + + // add the ordinal of the column as a key and the index of the column in the datareader as a value. + mapping.Add(col.Ordinal, readerIndex); + } } - if (!TableMappings.Contains (tableMapping)) - TableMappings.Add (tableMapping); } - - if (!table.Columns.Contains(dsColumnName)) - table.Columns.Add (dsColumnName, (Type) schemaRow ["DataType"]); - - if (!schemaRow["IsKey"].Equals (DBNull.Value)) - if ((bool) (schemaRow ["IsKey"])) - primaryKey.Add (table.Columns [dsColumnName]); + readerIndex++; } if (MissingSchemaAction == MissingSchemaAction.AddWithKey && primaryKey.Count > 0) table.PrimaryKey = (DataColumn[])(primaryKey.ToArray(typeof (DataColumn))); + + return mapping; } [MonoTODO] @@ -370,7 +451,50 @@ namespace System.Data.Common { [MonoTODO] public int Update (DataRow[] dataRows) { - throw new NotImplementedException (); // FIXME: Which mapping? + if (dataRows == null)
+ throw new ArgumentNullException("dataRows");
+
+ if (dataRows.Length == 0)
+ return 0;
+
+ if (dataRows[0] == null)
+ throw new ArgumentException("dataRows[0].");
+
+ DataTable table = dataRows[0].Table;
+ if (table == null)
+ throw new ArgumentException("table is null reference.");
+
+ // all rows must be in the same table
+ for (int i = 0; i < dataRows.Length; i++)
+ {
+ if (dataRows[i] == null)
+ throw new ArgumentException("dataRows[" + i + "].");
+ if (dataRows[i].Table != table)
+ throw new ArgumentException(
+ " DataRow["
+ + i
+ + "] is from a different DataTable than DataRow[0].");
+ }
+ + // get table mapping for this rows + DataTableMapping tableMapping = TableMappings.GetByDataSetTable(table.TableName);
+ if (tableMapping == null)
+ {
+ tableMapping = DataTableMappingCollection.GetTableMappingBySchemaAction(
+ TableMappings,
+ table.TableName,
+ table.TableName,
+ MissingMappingAction);
+ if (tableMapping == null)
+ tableMapping =
+ new DataTableMapping(
+ table.TableName,
+ table.TableName);
+ } + + DataRow[] copy = new DataRow [dataRows.Length]; + Array.Copy(dataRows, 0, copy, 0, dataRows.Length); + return Update(copy, tableMapping); } public override int Update (DataSet dataSet) @@ -397,6 +521,7 @@ namespace System.Data.Common { protected virtual int Update (DataRow[] dataRows, DataTableMapping tableMapping) { int updateCount = 0; + foreach (DataRow row in dataRows) { StatementType statementType = StatementType.Update; IDbCommand command = null; @@ -458,10 +583,28 @@ namespace System.Data.Common { } row.AcceptChanges (); } - updateCount += command.ExecuteNonQuery (); - OnRowUpdated (CreateRowUpdatedEvent (row, command, statementType, tableMapping)); + if (command.Connection.State == ConnectionState.Closed) + command.Connection.Open (); + + try + { + int tmp = command.ExecuteNonQuery (); + // 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; + OnRowUpdated (CreateRowUpdatedEvent (row, command, statementType, tableMapping)); + } + catch (Exception e) + { + if (ContinueUpdateOnError) + row.RowError = e.Message;// do somthing with the error + else + throw e; + } } + return updateCount; } |