2016-08-03 10:59:49 +00:00
//------------------------------------------------------------------------------
// <copyright file="CommandBuilder.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
2017-08-21 15:34:15 +00:00
// <owner current="true" primary="true">Microsoft</owner>
// <owner current="true" primary="false">Microsoft</owner>
2016-08-03 10:59:49 +00:00
//------------------------------------------------------------------------------
namespace System.Data.Common {
using System ;
using System.Collections ;
using System.ComponentModel ;
using System.Data ;
using System.Diagnostics ;
using System.Globalization ;
using System.Text ;
using System.Text.RegularExpressions ;
public abstract class DbCommandBuilder : Component { // V1.2.3300
private class ParameterNames {
private const string DefaultOriginalPrefix = "Original_" ;
private const string DefaultIsNullPrefix = "IsNull_" ;
// we use alternative prefix if the default prefix fails parametername validation
private const string AlternativeOriginalPrefix = "original" ;
private const string AlternativeIsNullPrefix = "isnull" ;
private const string AlternativeOriginalPrefix2 = "ORIGINAL" ;
private const string AlternativeIsNullPrefix2 = "ISNULL" ;
private string _originalPrefix ;
private string _isNullPrefix ;
private Regex _parameterNameParser ;
private DbCommandBuilder _dbCommandBuilder ;
private string [ ] _baseParameterNames ;
private string [ ] _originalParameterNames ;
private string [ ] _nullParameterNames ;
private bool [ ] _isMutatedName ;
private int _count ;
private int _genericParameterCount ;
private int _adjustedParameterNameMaxLength ;
internal ParameterNames ( DbCommandBuilder dbCommandBuilder , DbSchemaRow [ ] schemaRows ) {
_dbCommandBuilder = dbCommandBuilder ;
_baseParameterNames = new string [ schemaRows . Length ] ;
_originalParameterNames = new string [ schemaRows . Length ] ;
_nullParameterNames = new string [ schemaRows . Length ] ;
_isMutatedName = new bool [ schemaRows . Length ] ;
_count = schemaRows . Length ;
_parameterNameParser = new Regex ( _dbCommandBuilder . ParameterNamePattern , RegexOptions . ExplicitCapture | RegexOptions . Singleline ) ;
SetAndValidateNamePrefixes ( ) ;
_adjustedParameterNameMaxLength = GetAdjustedParameterNameMaxLength ( ) ;
// Generate the baseparameter names and remove conflicting names
// No names will be generated for any name that is rejected due to invalid prefix, regex violation or
// name conflict after mutation.
// All null values will be replaced with generic parameter names
//
for ( int i = 0 ; i < schemaRows . Length ; i + + ) {
if ( null = = schemaRows [ i ] ) {
continue ;
}
bool isMutatedName = false ;
string columnName = schemaRows [ i ] . ColumnName ;
// all names that start with original- or isNullPrefix are invalid
if ( null ! = _originalPrefix ) {
if ( columnName . StartsWith ( _originalPrefix , StringComparison . OrdinalIgnoreCase ) ) {
continue ;
}
}
if ( null ! = _isNullPrefix ) {
if ( columnName . StartsWith ( _isNullPrefix , StringComparison . OrdinalIgnoreCase ) ) {
continue ;
}
}
// Mutate name if it contains space(s)
if ( columnName . IndexOf ( ' ' ) > = 0 ) {
columnName = columnName . Replace ( ' ' , '_' ) ;
isMutatedName = true ;
}
// Validate name against regular expression
if ( ! _parameterNameParser . IsMatch ( columnName ) ) {
continue ;
}
// Validate name against adjusted max parametername length
if ( columnName . Length > _adjustedParameterNameMaxLength ) {
continue ;
}
_baseParameterNames [ i ] = columnName ;
_isMutatedName [ i ] = isMutatedName ;
}
EliminateConflictingNames ( ) ;
// Generate names for original- and isNullparameters
// no names will be generated if the prefix failed parametername validation
for ( int i = 0 ; i < schemaRows . Length ; i + + ) {
if ( null ! = _baseParameterNames [ i ] ) {
if ( null ! = _originalPrefix ) {
_originalParameterNames [ i ] = _originalPrefix + _baseParameterNames [ i ] ;
}
if ( null ! = _isNullPrefix ) {
// don't bother generating an 'IsNull' name if it's not used
if ( schemaRows [ i ] . AllowDBNull ) {
_nullParameterNames [ i ] = _isNullPrefix + _baseParameterNames [ i ] ;
}
}
}
}
ApplyProviderSpecificFormat ( ) ;
GenerateMissingNames ( schemaRows ) ;
}
private void SetAndValidateNamePrefixes ( ) {
if ( _parameterNameParser . IsMatch ( DefaultIsNullPrefix ) ) {
_isNullPrefix = DefaultIsNullPrefix ;
}
else if ( _parameterNameParser . IsMatch ( AlternativeIsNullPrefix ) ) {
_isNullPrefix = AlternativeIsNullPrefix ;
}
else if ( _parameterNameParser . IsMatch ( AlternativeIsNullPrefix2 ) ) {
_isNullPrefix = AlternativeIsNullPrefix2 ;
}
else {
_isNullPrefix = null ;
}
if ( _parameterNameParser . IsMatch ( DefaultOriginalPrefix ) ) {
_originalPrefix = DefaultOriginalPrefix ;
}
else if ( _parameterNameParser . IsMatch ( AlternativeOriginalPrefix ) ) {
_originalPrefix = AlternativeOriginalPrefix ;
}
else if ( _parameterNameParser . IsMatch ( AlternativeOriginalPrefix2 ) ) {
_originalPrefix = AlternativeOriginalPrefix2 ;
}
else {
_originalPrefix = null ;
}
}
private void ApplyProviderSpecificFormat ( ) {
for ( int i = 0 ; i < _baseParameterNames . Length ; i + + ) {
if ( null ! = _baseParameterNames [ i ] ) {
_baseParameterNames [ i ] = _dbCommandBuilder . GetParameterName ( _baseParameterNames [ i ] ) ;
}
if ( null ! = _originalParameterNames [ i ] ) {
_originalParameterNames [ i ] = _dbCommandBuilder . GetParameterName ( _originalParameterNames [ i ] ) ;
}
if ( null ! = _nullParameterNames [ i ] ) {
_nullParameterNames [ i ] = _dbCommandBuilder . GetParameterName ( _nullParameterNames [ i ] ) ;
}
}
}
private void EliminateConflictingNames ( ) {
//
for ( int i = 0 ; i < _count - 1 ; i + + ) {
string name = _baseParameterNames [ i ] ;
if ( null ! = name ) {
for ( int j = i + 1 ; j < _count ; j + + ) {
if ( ADP . CompareInsensitiveInvariant ( name , _baseParameterNames [ j ] ) ) {
// found duplicate name
// the name unchanged name wins
int iMutatedName = _isMutatedName [ j ] ? j : i ;
Debug . Assert ( _isMutatedName [ iMutatedName ] , String . Format ( CultureInfo . InvariantCulture , "{0} expected to be a mutated name" , _baseParameterNames [ iMutatedName ] ) ) ;
_baseParameterNames [ iMutatedName ] = null ; // null out the culprit
}
}
}
}
}
// Generates parameternames that couldn't be generated from columnname
internal void GenerateMissingNames ( DbSchemaRow [ ] schemaRows ) {
// foreach name in base names
// if base name is null
// for base, original and nullnames (null names only if nullable)
// do
// generate name based on current index
// increment index
// search name in base names
// loop while name occures in base names
// end for
// end foreach
string name ;
for ( int i = 0 ; i < _baseParameterNames . Length ; i + + ) {
name = _baseParameterNames [ i ] ;
if ( null = = name ) {
_baseParameterNames [ i ] = GetNextGenericParameterName ( ) ;
_originalParameterNames [ i ] = GetNextGenericParameterName ( ) ;
// don't bother generating an 'IsNull' name if it's not used
if ( ( null ! = schemaRows [ i ] ) & & schemaRows [ i ] . AllowDBNull ) {
_nullParameterNames [ i ] = GetNextGenericParameterName ( ) ;
}
}
}
}
private int GetAdjustedParameterNameMaxLength ( ) {
int maxPrefixLength = Math . Max (
( null ! = _isNullPrefix ? _isNullPrefix . Length : 0 ) ,
( null ! = _originalPrefix ? _originalPrefix . Length : 0 )
) + _dbCommandBuilder . GetParameterName ( "" ) . Length ;
return _dbCommandBuilder . ParameterNameMaxLength - maxPrefixLength ;
}
private string GetNextGenericParameterName ( ) {
string name ;
bool nameExist ;
do {
nameExist = false ;
_genericParameterCount + + ;
name = _dbCommandBuilder . GetParameterName ( _genericParameterCount ) ;
for ( int i = 0 ; i < _baseParameterNames . Length ; i + + ) {
if ( ADP . CompareInsensitiveInvariant ( _baseParameterNames [ i ] , name ) ) {
nameExist = true ;
break ;
}
}
} while ( nameExist ) ;
return name ;
}
internal string GetBaseParameterName ( int index ) {
return ( _baseParameterNames [ index ] ) ;
}
internal string GetOriginalParameterName ( int index ) {
return ( _originalParameterNames [ index ] ) ;
}
internal string GetNullParameterName ( int index ) {
return ( _nullParameterNames [ index ] ) ;
}
}
private const string DeleteFrom = "DELETE FROM " ;
private const string InsertInto = "INSERT INTO " ;
private const string DefaultValues = " DEFAULT VALUES" ;
private const string Values = " VALUES " ;
private const string Update = "UPDATE " ;
private const string Set = " SET " ;
private const string Where = " WHERE " ;
private const string SpaceLeftParenthesis = " (" ;
private const string Comma = ", " ;
private const string Equal = " = " ;
private const string LeftParenthesis = "(" ;
private const string RightParenthesis = ")" ;
private const string NameSeparator = "." ;
private const string IsNull = " IS NULL" ;
private const string EqualOne = " = 1" ;
private const string And = " AND " ;
private const string Or = " OR " ;
private DbDataAdapter _dataAdapter ;
private DbCommand _insertCommand ;
private DbCommand _updateCommand ;
private DbCommand _deleteCommand ;
private MissingMappingAction _missingMappingAction ;
private ConflictOption _conflictDetection = ConflictOption . CompareAllSearchableValues ;
private bool _setAllValues = false ;
private bool _hasPartialPrimaryKey = false ;
private DataTable _dbSchemaTable ;
private DbSchemaRow [ ] _dbSchemaRows ;
private string [ ] _sourceColumnNames ;
private ParameterNames _parameterNames = null ;
private string _quotedBaseTableName ;
// quote strings to use around SQL object names
private CatalogLocation _catalogLocation = CatalogLocation . Start ;
private string _catalogSeparator = NameSeparator ;
private string _schemaSeparator = NameSeparator ;
private string _quotePrefix = "" ;
private string _quoteSuffix = "" ;
private string _parameterNamePattern = null ;
private string _parameterMarkerFormat = null ;
private int _parameterNameMaxLength = 0 ;
protected DbCommandBuilder ( ) : base ( ) { // V1.2.3300
}
[
DefaultValueAttribute ( ConflictOption . CompareAllSearchableValues ) ,
ResCategoryAttribute ( Res . DataCategory_Update ) ,
ResDescriptionAttribute ( Res . DbCommandBuilder_ConflictOption ) ,
]
virtual public ConflictOption ConflictOption { // V1.2.3300
get {
return _conflictDetection ;
}
set {
switch ( value ) {
case ConflictOption . CompareAllSearchableValues :
case ConflictOption . CompareRowVersion :
case ConflictOption . OverwriteChanges :
_conflictDetection = value ;
break ;
default :
throw ADP . InvalidConflictOptions ( value ) ;
}
}
}
[
DefaultValueAttribute ( CatalogLocation . Start ) ,
ResCategoryAttribute ( Res . DataCategory_Schema ) ,
ResDescriptionAttribute ( Res . DbCommandBuilder_CatalogLocation ) ,
]
virtual public CatalogLocation CatalogLocation { // V1.2.3300, MDAC 79449
get {
return _catalogLocation ;
}
set {
if ( null ! = _dbSchemaTable ) {
throw ADP . NoQuoteChange ( ) ;
}
switch ( value ) {
case CatalogLocation . Start :
case CatalogLocation . End :
_catalogLocation = value ;
break ;
default :
throw ADP . InvalidCatalogLocation ( value ) ;
}
}
}
[
DefaultValueAttribute ( DbCommandBuilder . NameSeparator ) ,
ResCategoryAttribute ( Res . DataCategory_Schema ) ,
ResDescriptionAttribute ( Res . DbCommandBuilder_CatalogSeparator ) ,
]
virtual public string CatalogSeparator { // V1.2.3300, MDAC 79449
get {
string catalogSeparator = _catalogSeparator ;
return ( ( ( null ! = catalogSeparator ) & & ( 0 < catalogSeparator . Length ) ) ? catalogSeparator : NameSeparator ) ;
}
set {
if ( null ! = _dbSchemaTable ) {
throw ADP . NoQuoteChange ( ) ;
}
_catalogSeparator = value ;
}
}
[
Browsable ( false ) ,
DesignerSerializationVisibility ( DesignerSerializationVisibility . Hidden ) ,
ResDescriptionAttribute ( Res . DbCommandBuilder_DataAdapter ) ,
]
public DbDataAdapter DataAdapter { // V1.2.3300
get {
return _dataAdapter ;
}
set {
if ( _dataAdapter ! = value ) {
RefreshSchema ( ) ;
if ( null ! = _dataAdapter ) {
// derived should remove event handler from old adapter
SetRowUpdatingHandler ( _dataAdapter ) ;
_dataAdapter = null ;
}
if ( null ! = value ) {
// derived should add event handler to new adapter
SetRowUpdatingHandler ( value ) ;
_dataAdapter = value ;
}
}
}
}
internal int ParameterNameMaxLength {
get {
return _parameterNameMaxLength ;
}
}
internal string ParameterNamePattern {
get {
return _parameterNamePattern ;
}
}
private string QuotedBaseTableName {
get {
return _quotedBaseTableName ;
}
}
[
DefaultValueAttribute ( "" ) ,
ResCategoryAttribute ( Res . DataCategory_Schema ) ,
ResDescriptionAttribute ( Res . DbCommandBuilder_QuotePrefix ) ,
]
virtual public string QuotePrefix { // V1.2.3300, XXXCommandBuilder V1.0.3300
get {
string quotePrefix = _quotePrefix ;
return ( ( null ! = quotePrefix ) ? quotePrefix : ADP . StrEmpty ) ;
}
set {
if ( null ! = _dbSchemaTable ) {
throw ADP . NoQuoteChange ( ) ;
}
_quotePrefix = value ;
}
}
[
DefaultValueAttribute ( "" ) ,
ResCategoryAttribute ( Res . DataCategory_Schema ) ,
ResDescriptionAttribute ( Res . DbCommandBuilder_QuoteSuffix ) ,
]
virtual public string QuoteSuffix { // V1.2.3300, XXXCommandBuilder V1.0.3300
get {
string quoteSuffix = _quoteSuffix ;
return ( ( null ! = quoteSuffix ) ? quoteSuffix : ADP . StrEmpty ) ;
}
set {
if ( null ! = _dbSchemaTable ) {
throw ADP . NoQuoteChange ( ) ;
}
_quoteSuffix = value ;
}
}
[
DefaultValueAttribute ( DbCommandBuilder . NameSeparator ) ,
ResCategoryAttribute ( Res . DataCategory_Schema ) ,
ResDescriptionAttribute ( Res . DbCommandBuilder_SchemaSeparator ) ,
]
virtual public string SchemaSeparator { // V1.2.3300, MDAC 79449
get {
string schemaSeparator = _schemaSeparator ;
return ( ( ( null ! = schemaSeparator ) & & ( 0 < schemaSeparator . Length ) ) ? schemaSeparator : NameSeparator ) ;
}
set {
if ( null ! = _dbSchemaTable ) {
throw ADP . NoQuoteChange ( ) ;
}
_schemaSeparator = value ;
}
}
[
DefaultValueAttribute ( false ) ,
ResCategoryAttribute ( Res . DataCategory_Schema ) ,
ResDescriptionAttribute ( Res . DbCommandBuilder_SetAllValues ) ,
]
public bool SetAllValues {
get {
return _setAllValues ;
}
set {
_setAllValues = value ;
}
}
private DbCommand InsertCommand {
get {
return _insertCommand ;
}
set {
_insertCommand = value ;
}
}
private DbCommand UpdateCommand {
get {
return _updateCommand ;
}
set {
_updateCommand = value ;
}
}
private DbCommand DeleteCommand {
get {
return _deleteCommand ;
}
set {
_deleteCommand = value ;
}
}
private void BuildCache ( bool closeConnection , DataRow dataRow , bool useColumnsForParameterNames ) { // V1.2.3300
// Don't bother building the cache if it's done already; wait for
// the user to call RefreshSchema first.
if ( ( null ! = _dbSchemaTable ) & & ( ! useColumnsForParameterNames | | ( null ! = _parameterNames ) ) ) {
return ;
}
DataTable schemaTable = null ;
DbCommand srcCommand = GetSelectCommand ( ) ;
DbConnection connection = srcCommand . Connection ;
if ( null = = connection ) {
throw ADP . MissingSourceCommandConnection ( ) ;
}
try {
if ( 0 = = ( ConnectionState . Open & connection . State ) ) {
connection . Open ( ) ;
}
else {
closeConnection = false ;
}
if ( useColumnsForParameterNames ) {
DataTable dataTable = connection . GetSchema ( DbMetaDataCollectionNames . DataSourceInformation ) ;
if ( dataTable . Rows . Count = = 1 ) {
_parameterNamePattern = dataTable . Rows [ 0 ] [ DbMetaDataColumnNames . ParameterNamePattern ] as string ;
_parameterMarkerFormat = dataTable . Rows [ 0 ] [ DbMetaDataColumnNames . ParameterMarkerFormat ] as string ;
object oParameterNameMaxLength = dataTable . Rows [ 0 ] [ DbMetaDataColumnNames . ParameterNameMaxLength ] ;
_parameterNameMaxLength = ( oParameterNameMaxLength is int ) ? ( int ) oParameterNameMaxLength : 0 ;
// note that we protect against errors in the xml file!
if ( 0 = = _parameterNameMaxLength | | null = = _parameterNamePattern | | null = = _parameterMarkerFormat ) {
useColumnsForParameterNames = false ;
}
}
else {
Debug . Assert ( false , "Rowcount expected to be 1" ) ;
useColumnsForParameterNames = false ;
}
}
schemaTable = GetSchemaTable ( srcCommand ) ;
}
finally {
if ( closeConnection ) {
connection . Close ( ) ;
}
}
if ( null = = schemaTable ) {
throw ADP . DynamicSQLNoTableInfo ( ) ;
}
#if DEBUG
//if (AdapterSwitches.DbCommandBuilder.TraceVerbose) {
// ADP.TraceDataTable("DbCommandBuilder", schemaTable);
//}
#endif
BuildInformation ( schemaTable ) ;
_dbSchemaTable = schemaTable ;
DbSchemaRow [ ] schemaRows = _dbSchemaRows ;
string [ ] srcColumnNames = new string [ schemaRows . Length ] ;
for ( int i = 0 ; i < schemaRows . Length ; + + i ) {
if ( null ! = schemaRows [ i ] ) {
srcColumnNames [ i ] = schemaRows [ i ] . ColumnName ;
}
}
_sourceColumnNames = srcColumnNames ;
if ( useColumnsForParameterNames ) {
_parameterNames = new ParameterNames ( this , schemaRows ) ;
}
ADP . BuildSchemaTableInfoTableNames ( srcColumnNames ) ;
}
virtual protected DataTable GetSchemaTable ( DbCommand sourceCommand ) {
using ( IDataReader dataReader = sourceCommand . ExecuteReader ( CommandBehavior . SchemaOnly | CommandBehavior . KeyInfo ) ) {
return dataReader . GetSchemaTable ( ) ;
}
}
private void BuildInformation ( DataTable schemaTable ) {
DbSchemaRow [ ] rows = DbSchemaRow . GetSortedSchemaRows ( schemaTable , false ) ; // MDAC 60609
if ( ( null = = rows ) | | ( 0 = = rows . Length ) ) {
throw ADP . DynamicSQLNoTableInfo ( ) ;
}
string baseServerName = "" ; // MDAC 72721, 73599
string baseCatalogName = "" ;
string baseSchemaName = "" ;
string baseTableName = null ;
for ( int i = 0 ; i < rows . Length ; + + i ) {
DbSchemaRow row = rows [ i ] ;
string tableName = row . BaseTableName ;
if ( ( null = = tableName ) | | ( 0 = = tableName . Length ) ) {
rows [ i ] = null ;
continue ;
}
string serverName = row . BaseServerName ;
string catalogName = row . BaseCatalogName ;
string schemaName = row . BaseSchemaName ;
if ( null = = serverName ) {
serverName = "" ;
}
if ( null = = catalogName ) {
catalogName = "" ;
}
if ( null = = schemaName ) {
schemaName = "" ;
}
if ( null = = baseTableName ) {
baseServerName = serverName ;
baseCatalogName = catalogName ;
baseSchemaName = schemaName ;
baseTableName = tableName ;
}
else if ( ( 0 ! = ADP . SrcCompare ( baseTableName , tableName ) )
| | ( 0 ! = ADP . SrcCompare ( baseSchemaName , schemaName ) )
| | ( 0 ! = ADP . SrcCompare ( baseCatalogName , catalogName ) )
| | ( 0 ! = ADP . SrcCompare ( baseServerName , serverName ) ) ) {
throw ADP . DynamicSQLJoinUnsupported ( ) ;
}
}
if ( 0 = = baseServerName . Length ) {
baseServerName = null ;
}
if ( 0 = = baseCatalogName . Length ) {
baseServerName = null ;
baseCatalogName = null ;
}
if ( 0 = = baseSchemaName . Length ) {
baseServerName = null ;
baseCatalogName = null ;
baseSchemaName = null ;
}
if ( ( null = = baseTableName ) | | ( 0 = = baseTableName . Length ) ) {
throw ADP . DynamicSQLNoTableInfo ( ) ;
}
CatalogLocation location = CatalogLocation ;
string catalogSeparator = CatalogSeparator ;
string schemaSeparator = SchemaSeparator ;
string quotePrefix = QuotePrefix ;
string quoteSuffix = QuoteSuffix ;
if ( ! ADP . IsEmpty ( quotePrefix ) & & ( - 1 ! = baseTableName . IndexOf ( quotePrefix , StringComparison . Ordinal ) ) ) {
throw ADP . DynamicSQLNestedQuote ( baseTableName , quotePrefix ) ;
}
if ( ! ADP . IsEmpty ( quoteSuffix ) & & ( - 1 ! = baseTableName . IndexOf ( quoteSuffix , StringComparison . Ordinal ) ) ) {
throw ADP . DynamicSQLNestedQuote ( baseTableName , quoteSuffix ) ;
}
System . Text . StringBuilder builder = new System . Text . StringBuilder ( ) ;
if ( CatalogLocation . Start = = location ) {
// MDAC 79449
if ( null ! = baseServerName ) {
builder . Append ( ADP . BuildQuotedString ( quotePrefix , quoteSuffix , baseServerName ) ) ;
builder . Append ( catalogSeparator ) ;
}
if ( null ! = baseCatalogName ) {
builder . Append ( ADP . BuildQuotedString ( quotePrefix , quoteSuffix , baseCatalogName ) ) ;
builder . Append ( catalogSeparator ) ;
}
//
}
if ( null ! = baseSchemaName ) {
builder . Append ( ADP . BuildQuotedString ( quotePrefix , quoteSuffix , baseSchemaName ) ) ;
builder . Append ( schemaSeparator ) ;
}
//
builder . Append ( ADP . BuildQuotedString ( quotePrefix , quoteSuffix , baseTableName ) ) ;
if ( CatalogLocation . End = = location ) {
// MDAC 79449
if ( null ! = baseServerName ) {
builder . Append ( catalogSeparator ) ;
builder . Append ( ADP . BuildQuotedString ( quotePrefix , quoteSuffix , baseServerName ) ) ;
}
if ( null ! = baseCatalogName ) {
builder . Append ( catalogSeparator ) ;
builder . Append ( ADP . BuildQuotedString ( quotePrefix , quoteSuffix , baseCatalogName ) ) ;
}
}
_quotedBaseTableName = builder . ToString ( ) ;
_hasPartialPrimaryKey = false ;
foreach ( DbSchemaRow row in rows ) {
if ( ( null ! = row ) & & ( row . IsKey | | row . IsUnique ) & & ! row . IsLong & & ! row . IsRowVersion & & row . IsHidden ) {
_hasPartialPrimaryKey = true ;
break ;
}
}
_dbSchemaRows = rows ;
}
private DbCommand BuildDeleteCommand ( DataTableMapping mappings , DataRow dataRow ) {
DbCommand command = InitializeCommand ( DeleteCommand ) ;
StringBuilder builder = new StringBuilder ( ) ;
int parameterCount = 0 ;
Debug . Assert ( ! ADP . IsEmpty ( _quotedBaseTableName ) , "no table name" ) ;
builder . Append ( DeleteFrom ) ;
builder . Append ( QuotedBaseTableName ) ;
parameterCount = BuildWhereClause ( mappings , dataRow , builder , command , parameterCount , false ) ;
command . CommandText = builder . ToString ( ) ;
RemoveExtraParameters ( command , parameterCount ) ;
DeleteCommand = command ;
return command ;
}
private DbCommand BuildInsertCommand ( DataTableMapping mappings , DataRow dataRow ) {
DbCommand command = InitializeCommand ( InsertCommand ) ;
StringBuilder builder = new StringBuilder ( ) ;
int parameterCount = 0 ;
string nextSeparator = SpaceLeftParenthesis ;
Debug . Assert ( ! ADP . IsEmpty ( _quotedBaseTableName ) , "no table name" ) ;
builder . Append ( InsertInto ) ;
builder . Append ( QuotedBaseTableName ) ;
// search for the columns in that base table, to be the column clause
DbSchemaRow [ ] schemaRows = _dbSchemaRows ;
string [ ] parameterName = new string [ schemaRows . Length ] ;
for ( int i = 0 ; i < schemaRows . Length ; + + i ) {
DbSchemaRow row = schemaRows [ i ] ;
if ( ( null = = row ) | | ( 0 = = row . BaseColumnName . Length ) | | ! IncludeInInsertValues ( row ) )
continue ;
object currentValue = null ;
string sourceColumn = _sourceColumnNames [ i ] ;
// If we're building a statement for a specific row, then check the
// values to see whether the column should be included in the insert
// statement or not
if ( ( null ! = mappings ) & & ( null ! = dataRow ) ) {
DataColumn dataColumn = GetDataColumn ( sourceColumn , mappings , dataRow ) ;
if ( null = = dataColumn )
continue ;
// Don't bother inserting if the column is readonly in both the data
// set and the back end.
if ( row . IsReadOnly & & dataColumn . ReadOnly )
continue ;
currentValue = GetColumnValue ( dataRow , dataColumn , DataRowVersion . Current ) ;
// If the value is null, and the column doesn't support nulls, then
// the user is requesting the server-specified default value, so don't
// include it in the set-list.
if ( ! row . AllowDBNull & & ( null = = currentValue | | Convert . IsDBNull ( currentValue ) ) )
continue ;
}
builder . Append ( nextSeparator ) ;
nextSeparator = Comma ;
builder . Append ( QuotedColumn ( row . BaseColumnName ) ) ;
parameterName [ parameterCount ] = CreateParameterForValue (
command ,
GetBaseParameterName ( i ) ,
sourceColumn ,
DataRowVersion . Current ,
parameterCount ,
currentValue ,
row , StatementType . Insert , false
) ;
parameterCount + + ;
}
if ( 0 = = parameterCount )
builder . Append ( DefaultValues ) ;
else {
builder . Append ( RightParenthesis ) ;
builder . Append ( Values ) ;
builder . Append ( LeftParenthesis ) ;
builder . Append ( parameterName [ 0 ] ) ;
for ( int i = 1 ; i < parameterCount ; + + i ) {
builder . Append ( Comma ) ;
builder . Append ( parameterName [ i ] ) ;
}
builder . Append ( RightParenthesis ) ;
}
command . CommandText = builder . ToString ( ) ;
RemoveExtraParameters ( command , parameterCount ) ;
InsertCommand = command ;
return command ;
}
private DbCommand BuildUpdateCommand ( DataTableMapping mappings , DataRow dataRow ) {
DbCommand command = InitializeCommand ( UpdateCommand ) ;
StringBuilder builder = new StringBuilder ( ) ;
string nextSeparator = Set ;
int parameterCount = 0 ;
Debug . Assert ( ! ADP . IsEmpty ( _quotedBaseTableName ) , "no table name" ) ;
builder . Append ( Update ) ;
builder . Append ( QuotedBaseTableName ) ;
// search for the columns in that base table, to build the set clause
DbSchemaRow [ ] schemaRows = _dbSchemaRows ;
for ( int i = 0 ; i < schemaRows . Length ; + + i ) {
DbSchemaRow row = schemaRows [ i ] ;
if ( ( null = = row ) | | ( 0 = = row . BaseColumnName . Length ) | | ! IncludeInUpdateSet ( row ) )
continue ;
object currentValue = null ;
string sourceColumn = _sourceColumnNames [ i ] ;
// If we're building a statement for a specific row, then check the
// values to see whether the column should be included in the update
// statement or not
if ( ( null ! = mappings ) & & ( null ! = dataRow ) ) {
DataColumn dataColumn = GetDataColumn ( sourceColumn , mappings , dataRow ) ;
if ( null = = dataColumn )
continue ;
// Don't bother updating if the column is readonly in both the data
// set and the back end.
if ( row . IsReadOnly & & dataColumn . ReadOnly )
continue ;
// Unless specifically directed to do so, we will not automatically update
// a column with it's original value, which means that we must determine
// whether the value has changed locally, before we send it up.
currentValue = GetColumnValue ( dataRow , dataColumn , DataRowVersion . Current ) ;
if ( ! SetAllValues ) {
object originalValue = GetColumnValue ( dataRow , dataColumn , DataRowVersion . Original ) ;
if ( ( originalValue = = currentValue )
| | ( ( null ! = originalValue ) & & originalValue . Equals ( currentValue ) ) ) {
continue ;
}
}
}
builder . Append ( nextSeparator ) ;
nextSeparator = Comma ;
builder . Append ( QuotedColumn ( row . BaseColumnName ) ) ;
builder . Append ( Equal ) ;
builder . Append (
CreateParameterForValue (
command ,
GetBaseParameterName ( i ) ,
sourceColumn ,
DataRowVersion . Current ,
parameterCount ,
currentValue ,
row , StatementType . Update , false
)
) ;
parameterCount + + ;
}
// It is an error to attempt an update when there's nothing to update;
bool skipRow = ( 0 = = parameterCount ) ;
parameterCount = BuildWhereClause ( mappings , dataRow , builder , command , parameterCount , true ) ;
command . CommandText = builder . ToString ( ) ;
RemoveExtraParameters ( command , parameterCount ) ;
UpdateCommand = command ;
return ( skipRow ) ? null : command ;
}
private int BuildWhereClause (
DataTableMapping mappings ,
DataRow dataRow ,
StringBuilder builder ,
DbCommand command ,
int parameterCount ,
bool isUpdate
) {
string beginNewCondition = string . Empty ;
int whereCount = 0 ;
builder . Append ( Where ) ;
builder . Append ( LeftParenthesis ) ;
DbSchemaRow [ ] schemaRows = _dbSchemaRows ;
for ( int i = 0 ; i < schemaRows . Length ; + + i ) {
DbSchemaRow row = schemaRows [ i ] ;
if ( ( null = = row ) | | ( 0 = = row . BaseColumnName . Length ) | | ! IncludeInWhereClause ( row , isUpdate ) ) {
continue ;
}
builder . Append ( beginNewCondition ) ;
beginNewCondition = And ;
object value = null ;
string sourceColumn = _sourceColumnNames [ i ] ;
string baseColumnName = QuotedColumn ( row . BaseColumnName ) ;
if ( ( null ! = mappings ) & & ( null ! = dataRow ) )
value = GetColumnValue ( dataRow , sourceColumn , mappings , DataRowVersion . Original ) ;
if ( ! row . AllowDBNull ) {
// (<baseColumnName> = ?)
builder . Append ( LeftParenthesis ) ;
builder . Append ( baseColumnName ) ;
builder . Append ( Equal ) ;
builder . Append (
CreateParameterForValue (
command ,
GetOriginalParameterName ( i ) ,
sourceColumn ,
DataRowVersion . Original ,
parameterCount ,
value ,
row , ( isUpdate ? StatementType . Update : StatementType . Delete ) , true
)
) ;
parameterCount + + ;
builder . Append ( RightParenthesis ) ;
}
else {
// ((? = 1 AND <baseColumnName> IS NULL) OR (<baseColumnName> = ?))
builder . Append ( LeftParenthesis ) ;
builder . Append ( LeftParenthesis ) ;
builder . Append (
CreateParameterForNullTest (
command ,
GetNullParameterName ( i ) ,
sourceColumn ,
DataRowVersion . Original ,
parameterCount ,
value ,
row , ( isUpdate ? StatementType . Update : StatementType . Delete ) , true
)
) ;
parameterCount + + ;
builder . Append ( EqualOne ) ;
builder . Append ( And ) ;
builder . Append ( baseColumnName ) ;
builder . Append ( IsNull ) ;
builder . Append ( RightParenthesis ) ;
builder . Append ( Or ) ;
builder . Append ( LeftParenthesis ) ;
builder . Append ( baseColumnName ) ;
builder . Append ( Equal ) ;
builder . Append (
CreateParameterForValue (
command ,
GetOriginalParameterName ( i ) ,
sourceColumn ,
DataRowVersion . Original ,
parameterCount ,
value ,
row , ( isUpdate ? StatementType . Update : StatementType . Delete ) , true
)
) ;
parameterCount + + ;
builder . Append ( RightParenthesis ) ;
builder . Append ( RightParenthesis ) ;
}
if ( IncrementWhereCount ( row ) ) {
whereCount + + ;
}
}
builder . Append ( RightParenthesis ) ;
if ( 0 = = whereCount ) {
if ( isUpdate ) {
if ( ConflictOption . CompareRowVersion = = ConflictOption ) {
throw ADP . DynamicSQLNoKeyInfoRowVersionUpdate ( ) ;
}
throw ADP . DynamicSQLNoKeyInfoUpdate ( ) ;
}
else {
if ( ConflictOption . CompareRowVersion = = ConflictOption ) {
throw ADP . DynamicSQLNoKeyInfoRowVersionDelete ( ) ;
}
throw ADP . DynamicSQLNoKeyInfoDelete ( ) ;
}
}
return parameterCount ;
}
private string CreateParameterForNullTest (
DbCommand command ,
string parameterName ,
string sourceColumn ,
DataRowVersion version ,
int parameterCount ,
object value ,
DbSchemaRow row ,
StatementType statementType ,
bool whereClause
) {
DbParameter p = GetNextParameter ( command , parameterCount ) ;
Debug . Assert ( ! ADP . IsEmpty ( sourceColumn ) , "empty source column" ) ;
if ( null = = parameterName ) {
p . ParameterName = GetParameterName ( 1 + parameterCount ) ;
}
else {
p . ParameterName = parameterName ;
}
p . Direction = ParameterDirection . Input ;
p . SourceColumn = sourceColumn ;
p . SourceVersion = version ;
p . SourceColumnNullMapping = true ;
p . Value = value ;
p . Size = 0 ; // don't specify parameter.Size so that we don't silently truncate to the metadata size
ApplyParameterInfo ( p , row . DataRow , statementType , whereClause ) ;
p . DbType = DbType . Int32 ;
p . Value = ADP . IsNull ( value ) ? DbDataAdapter . ParameterValueNullValue : DbDataAdapter . ParameterValueNonNullValue ;
if ( ! command . Parameters . Contains ( p ) ) {
command . Parameters . Add ( p ) ;
}
if ( null = = parameterName ) {
return GetParameterPlaceholder ( 1 + parameterCount ) ;
}
else {
Debug . Assert ( null ! = _parameterNames , "How can we have a parameterName without a _parameterNames collection?" ) ;
Debug . Assert ( null ! = _parameterMarkerFormat , "How can we have a _parameterNames collection but no _parameterMarkerFormat?" ) ;
return String . Format ( CultureInfo . InvariantCulture , _parameterMarkerFormat , parameterName ) ;
}
}
private string CreateParameterForValue (
DbCommand command ,
string parameterName ,
string sourceColumn ,
DataRowVersion version ,
int parameterCount ,
object value ,
DbSchemaRow row ,
StatementType statementType ,
bool whereClause
) {
DbParameter p = GetNextParameter ( command , parameterCount ) ;
if ( null = = parameterName ) {
p . ParameterName = GetParameterName ( 1 + parameterCount ) ;
}
else {
p . ParameterName = parameterName ;
}
p . Direction = ParameterDirection . Input ;
p . SourceColumn = sourceColumn ;
p . SourceVersion = version ;
p . SourceColumnNullMapping = false ;
p . Value = value ;
p . Size = 0 ; // don't specify parameter.Size so that we don't silently truncate to the metadata size
ApplyParameterInfo ( p , row . DataRow , statementType , whereClause ) ;
if ( ! command . Parameters . Contains ( p ) ) {
command . Parameters . Add ( p ) ;
}
if ( null = = parameterName ) {
return GetParameterPlaceholder ( 1 + parameterCount ) ;
}
else {
Debug . Assert ( null ! = _parameterNames , "How can we have a parameterName without a _parameterNames collection?" ) ;
Debug . Assert ( null ! = _parameterMarkerFormat , "How can we have a _parameterNames collection but no _parameterMarkerFormat?" ) ;
return String . Format ( CultureInfo . InvariantCulture , _parameterMarkerFormat , parameterName ) ;
}
}
override protected void Dispose ( bool disposing ) { // V1.2.3300, XXXCommandBuilder V1.0.3300
// MDAC 65459
if ( disposing ) {
// release mananged objects
DataAdapter = null ;
}
//release unmanaged objects
base . Dispose ( disposing ) ; // notify base classes
}
private DataTableMapping GetTableMapping ( DataRow dataRow ) {
DataTableMapping tableMapping = null ;
if ( null ! = dataRow ) {
DataTable dataTable = dataRow . Table ;
if ( null ! = dataTable ) {
DbDataAdapter adapter = DataAdapter ;
if ( null ! = adapter ) {
tableMapping = adapter . GetTableMapping ( dataTable ) ;
}
else {
string tableName = dataTable . TableName ;
tableMapping = new DataTableMapping ( tableName , tableName ) ;
}
}
}
return tableMapping ;
}
private string GetBaseParameterName ( int index ) {
if ( null ! = _parameterNames ) {
return ( _parameterNames . GetBaseParameterName ( index ) ) ;
}
else {
return null ;
}
}
private string GetOriginalParameterName ( int index ) {
if ( null ! = _parameterNames ) {
return ( _parameterNames . GetOriginalParameterName ( index ) ) ;
}
else {
return null ;
}
}
private string GetNullParameterName ( int index ) {
if ( null ! = _parameterNames ) {
return ( _parameterNames . GetNullParameterName ( index ) ) ;
}
else {
return null ;
}
}
private DbCommand GetSelectCommand ( ) { // V1.2.3300
DbCommand select = null ;
DbDataAdapter adapter = DataAdapter ;
if ( null ! = adapter ) {
if ( 0 = = _missingMappingAction ) {
_missingMappingAction = adapter . MissingMappingAction ;
}
select = ( DbCommand ) adapter . SelectCommand ;
}
if ( null = = select ) {
throw ADP . MissingSourceCommand ( ) ;
}
return select ;
}
// open connection is required by OleDb/OdbcCommandBuilder.QuoteIdentifier and UnquoteIdentifier
// to get literals quotes from the driver
internal DbConnection GetConnection ( ) {
DbDataAdapter adapter = DataAdapter ;
if ( adapter ! = null ) {
DbCommand select = ( DbCommand ) adapter . SelectCommand ;
if ( select ! = null ) {
return select . Connection ;
}
}
return null ;
}
public DbCommand GetInsertCommand ( ) { // V1.2.3300, XXXCommandBuilder V1.0.3300
return GetInsertCommand ( ( DataRow ) null , false ) ;
}
public DbCommand GetInsertCommand ( bool useColumnsForParameterNames ) {
return GetInsertCommand ( ( DataRow ) null , useColumnsForParameterNames ) ;
}
internal DbCommand GetInsertCommand ( DataRow dataRow , bool useColumnsForParameterNames ) {
BuildCache ( true , dataRow , useColumnsForParameterNames ) ;
BuildInsertCommand ( GetTableMapping ( dataRow ) , dataRow ) ;
return InsertCommand ;
}
public DbCommand GetUpdateCommand ( ) { // V1.2.3300, XXXCommandBuilder V1.0.3300
return GetUpdateCommand ( ( DataRow ) null , false ) ;
}
public DbCommand GetUpdateCommand ( bool useColumnsForParameterNames ) {
return GetUpdateCommand ( ( DataRow ) null , useColumnsForParameterNames ) ;
}
internal DbCommand GetUpdateCommand ( DataRow dataRow , bool useColumnsForParameterNames ) {
BuildCache ( true , dataRow , useColumnsForParameterNames ) ;
BuildUpdateCommand ( GetTableMapping ( dataRow ) , dataRow ) ;
return UpdateCommand ;
}
public DbCommand GetDeleteCommand ( ) { // V1.2.3300, XXXCommandBuilder V1.0.3300
return GetDeleteCommand ( ( DataRow ) null , false ) ;
}
public DbCommand GetDeleteCommand ( bool useColumnsForParameterNames ) {
return GetDeleteCommand ( ( DataRow ) null , useColumnsForParameterNames ) ;
}
internal DbCommand GetDeleteCommand ( DataRow dataRow , bool useColumnsForParameterNames ) {
BuildCache ( true , dataRow , useColumnsForParameterNames ) ;
BuildDeleteCommand ( GetTableMapping ( dataRow ) , dataRow ) ;
return DeleteCommand ;
}
private object GetColumnValue ( DataRow row , String columnName , DataTableMapping mappings , DataRowVersion version ) {
return GetColumnValue ( row , GetDataColumn ( columnName , mappings , row ) , version ) ;
}
private object GetColumnValue ( DataRow row , DataColumn column , DataRowVersion version ) {
object value = null ;
if ( null ! = column ) {
value = row [ column , version ] ;
}
return value ;
}
private DataColumn GetDataColumn ( string columnName , DataTableMapping tablemapping , DataRow row ) {
DataColumn column = null ;
if ( ! ADP . IsEmpty ( columnName ) ) {
column = tablemapping . GetDataColumn ( columnName , null , row . Table , _missingMappingAction , MissingSchemaAction . Error ) ;
}
return column ;
}
static private DbParameter GetNextParameter ( DbCommand command , int pcount ) {
DbParameter p ;
if ( pcount < command . Parameters . Count ) {
p = command . Parameters [ pcount ] ;
}
else {
p = command . CreateParameter ( ) ;
/ * if ( null = = p ) {
//
* /
}
Debug . Assert ( null ! = p , "null CreateParameter" ) ;
return p ;
}
private bool IncludeInInsertValues ( DbSchemaRow row ) {
//
return ( ! row . IsAutoIncrement & & ! row . IsHidden & & ! row . IsExpression & & ! row . IsRowVersion & & ! row . IsReadOnly ) ;
}
private bool IncludeInUpdateSet ( DbSchemaRow row ) {
//
return ( ! row . IsAutoIncrement & & ! row . IsRowVersion & & ! row . IsHidden & & ! row . IsReadOnly ) ;
}
private bool IncludeInWhereClause ( DbSchemaRow row , bool isUpdate ) {
bool flag = IncrementWhereCount ( row ) ;
if ( flag & & row . IsHidden ) { // MDAC 52564
if ( ConflictOption . CompareRowVersion = = ConflictOption ) {
throw ADP . DynamicSQLNoKeyInfoRowVersionUpdate ( ) ;
}
throw ADP . DynamicSQLNoKeyInfoUpdate ( ) ;
}
if ( ! flag & & ( ConflictOption . CompareAllSearchableValues = = ConflictOption ) ) {
// include other searchable values
flag = ! row . IsLong & & ! row . IsRowVersion & & ! row . IsHidden ;
}
return flag ;
}
private bool IncrementWhereCount ( DbSchemaRow row ) {
ConflictOption value = ConflictOption ;
switch ( value ) {
case ConflictOption . CompareAllSearchableValues :
case ConflictOption . OverwriteChanges :
// find the primary key
return ( row . IsKey | | row . IsUnique ) & & ! row . IsLong & & ! row . IsRowVersion ;
case ConflictOption . CompareRowVersion :
// or the row version
return ( ( ( row . IsKey | | row . IsUnique ) & & ! _hasPartialPrimaryKey ) | | row . IsRowVersion ) & & ! row . IsLong ;
default :
throw ADP . InvalidConflictOptions ( value ) ;
}
}
virtual protected DbCommand InitializeCommand ( DbCommand command ) { // V1.2.3300
if ( null = = command ) {
DbCommand select = GetSelectCommand ( ) ;
command = select . Connection . CreateCommand ( ) ;
/ * if ( null = = command ) {
//
* /
// the following properties are only initialized when the object is created
// all other properites are reinitialized on every row
/*command.Connection = select.Connection;*/ // initialized by CreateCommand
command . CommandTimeout = select . CommandTimeout ;
command . Transaction = select . Transaction ;
}
command . CommandType = CommandType . Text ;
command . UpdatedRowSource = UpdateRowSource . None ; // no select or output parameters expected
return command ;
}
private string QuotedColumn ( string column ) {
return ADP . BuildQuotedString ( QuotePrefix , QuoteSuffix , column ) ;
}
public virtual string QuoteIdentifier ( string unquotedIdentifier ) {
throw ADP . NotSupported ( ) ;
}
virtual public void RefreshSchema ( ) { // V1.2.3300, XXXCommandBuilder V1.0.3300
_dbSchemaTable = null ;
_dbSchemaRows = null ;
_sourceColumnNames = null ;
_quotedBaseTableName = null ;
DbDataAdapter adapter = DataAdapter ;
if ( null ! = adapter ) { // MDAC 66016
if ( InsertCommand = = adapter . InsertCommand ) {
adapter . InsertCommand = null ;
}
if ( UpdateCommand = = adapter . UpdateCommand ) {
adapter . UpdateCommand = null ;
}
if ( DeleteCommand = = adapter . DeleteCommand ) {
adapter . DeleteCommand = null ;
}
}
DbCommand command ;
if ( null ! = ( command = InsertCommand ) ) {
command . Dispose ( ) ;
}
if ( null ! = ( command = UpdateCommand ) ) {
command . Dispose ( ) ;
}
if ( null ! = ( command = DeleteCommand ) ) {
command . Dispose ( ) ;
}
InsertCommand = null ;
UpdateCommand = null ;
DeleteCommand = null ;
}
static private void RemoveExtraParameters ( DbCommand command , int usedParameterCount ) {
for ( int i = command . Parameters . Count - 1 ; i > = usedParameterCount ; - - i ) {
command . Parameters . RemoveAt ( i ) ;
}
}
protected void RowUpdatingHandler ( RowUpdatingEventArgs rowUpdatingEvent ) {
if ( null = = rowUpdatingEvent ) {
throw ADP . ArgumentNull ( "rowUpdatingEvent" ) ;
}
try {
if ( UpdateStatus . Continue = = rowUpdatingEvent . Status ) {
StatementType stmtType = rowUpdatingEvent . StatementType ;
DbCommand command = ( DbCommand ) rowUpdatingEvent . Command ;
if ( null ! = command ) {
switch ( stmtType ) {
case StatementType . Select :
Debug . Assert ( false , "how did we get here?" ) ;
return ; // don't mess with it
case StatementType . Insert :
command = InsertCommand ;
break ;
case StatementType . Update :
command = UpdateCommand ;
break ;
case StatementType . Delete :
command = DeleteCommand ;
break ;
default :
throw ADP . InvalidStatementType ( stmtType ) ;
}
if ( command ! = rowUpdatingEvent . Command ) {
command = ( DbCommand ) rowUpdatingEvent . Command ;
if ( ( null ! = command ) & & ( null = = command . Connection ) ) { // MDAC 87649
DbDataAdapter adapter = DataAdapter ;
DbCommand select = ( ( null ! = adapter ) ? ( ( DbCommand ) adapter . SelectCommand ) : null ) ;
if ( null ! = select ) {
command . Connection = ( DbConnection ) select . Connection ;
}
}
// user command, not a command builder command
}
else command = null ;
}
if ( null = = command ) {
RowUpdatingHandlerBuilder ( rowUpdatingEvent ) ;
}
}
}
catch ( Exception e ) {
//
if ( ! ADP . IsCatchableExceptionType ( e ) ) {
throw ;
}
ADP . TraceExceptionForCapture ( e ) ;
rowUpdatingEvent . Status = UpdateStatus . ErrorsOccurred ;
rowUpdatingEvent . Errors = e ;
}
}
private void RowUpdatingHandlerBuilder ( RowUpdatingEventArgs rowUpdatingEvent ) {
// MDAC 58710 - unable to tell Update method that Event opened connection and Update needs to close when done
// HackFix - the Update method will close the connection if command was null and returned command.Connection is same as SelectCommand.Connection
DataRow datarow = rowUpdatingEvent . Row ;
BuildCache ( false , datarow , false ) ;
DbCommand command ;
switch ( rowUpdatingEvent . StatementType ) {
case StatementType . Insert :
command = BuildInsertCommand ( rowUpdatingEvent . TableMapping , datarow ) ;
break ;
case StatementType . Update :
command = BuildUpdateCommand ( rowUpdatingEvent . TableMapping , datarow ) ;
break ;
case StatementType . Delete :
command = BuildDeleteCommand ( rowUpdatingEvent . TableMapping , datarow ) ;
break ;
#if DEBUG
case StatementType . Select :
Debug . Assert ( false , "how did we get here?" ) ;
goto default ;
#endif
default :
throw ADP . InvalidStatementType ( rowUpdatingEvent . StatementType ) ;
}
if ( null = = command ) {
if ( null ! = datarow ) {
datarow . AcceptChanges ( ) ;
}
rowUpdatingEvent . Status = UpdateStatus . SkipCurrentRow ;
}
rowUpdatingEvent . Command = command ;
}
public virtual string UnquoteIdentifier ( string quotedIdentifier ) {
throw ADP . NotSupported ( ) ;
}
abstract protected void ApplyParameterInfo ( DbParameter parameter , DataRow row , StatementType statementType , bool whereClause ) ; // V1.2.3300
abstract protected string GetParameterName ( int parameterOrdinal ) ; // V1.2.3300
abstract protected string GetParameterName ( string parameterName ) ;
abstract protected string GetParameterPlaceholder ( int parameterOrdinal ) ; // V1.2.3300
abstract protected void SetRowUpdatingHandler ( DbDataAdapter adapter ) ; // V1.2.3300
//
static internal string [ ] ParseProcedureName ( string name , string quotePrefix , string quoteSuffix ) {
// Procedure may consist of up to four parts:
// 0) Server
// 1) Catalog
// 2) Schema
// 3) ProcedureName
//
// Parse the string into four parts, allowing the last part to contain '.'s.
// If less than four period delimited parts, use the parts from procedure backwards.
//
const string Separator = "." ;
string [ ] qualifiers = new string [ 4 ] ;
if ( ! ADP . IsEmpty ( name ) ) {
bool useQuotes = ! ADP . IsEmpty ( quotePrefix ) & & ! ADP . IsEmpty ( quoteSuffix ) ;
int currentPos = 0 , parts ;
for ( parts = 0 ; ( parts < qualifiers . Length ) & & ( currentPos < name . Length ) ; + + parts ) {
int startPos = currentPos ;
// does the part begin with a quotePrefix?
if ( useQuotes & & ( name . IndexOf ( quotePrefix , currentPos , quotePrefix . Length , StringComparison . Ordinal ) = = currentPos ) ) {
currentPos + = quotePrefix . Length ; // move past the quotePrefix
// search for the quoteSuffix (or end of string)
while ( currentPos < name . Length ) {
currentPos = name . IndexOf ( quoteSuffix , currentPos , StringComparison . Ordinal ) ;
if ( currentPos < 0 ) {
// error condition, no quoteSuffix
currentPos = name . Length ;
break ;
}
else {
currentPos + = quoteSuffix . Length ; // move past the quoteSuffix
// is this a double quoteSuffix?
if ( ( currentPos < name . Length ) & & ( name . IndexOf ( quoteSuffix , currentPos , quoteSuffix . Length , StringComparison . Ordinal ) = = currentPos ) ) {
// a second quoteSuffix, continue search for terminating quoteSuffix
currentPos + = quoteSuffix . Length ; // move past the second quoteSuffix
}
else {
// found the terminating quoteSuffix
break ;
}
}
}
}
// search for separator (either no quotePrefix or already past quoteSuffix)
if ( currentPos < name . Length ) {
currentPos = name . IndexOf ( Separator , currentPos , StringComparison . Ordinal ) ;
if ( ( currentPos < 0 ) | | ( parts = = qualifiers . Length - 1 ) ) {
// last part that can be found
currentPos = name . Length ;
}
}
qualifiers [ parts ] = name . Substring ( startPos , currentPos - startPos ) ;
currentPos + = Separator . Length ;
}
// allign the qualifiers if we had less than MaxQualifiers
for ( int j = qualifiers . Length - 1 ; 0 < = j ; - - j ) {
qualifiers [ j ] = ( ( 0 < parts ) ? qualifiers [ - - parts ] : null ) ;
}
}
return qualifiers ;
}
}
}