Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataEntity / System / Data / Map / Update / Internal / FunctionUpdateCommand.cs / 2 / FunctionUpdateCommand.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Data.Common.CommandTrees; using System.Data.Metadata.Edm; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data.Common.CommandTrees.Internal; using System.Data.Common.Utils; using System.Diagnostics; using System.Data.Common; using System.Data.Objects; using System.Data.EntityClient; using System.Globalization; using System.Data.Entity; using System.Linq; namespace System.Data.Mapping.Update.Internal { ////// Aggregates information about a modification command delegated to a store function. /// internal sealed class FunctionUpdateCommand : UpdateCommand { #region Constructors ////// Initialize a new function command. Initializes the command object. /// /// Function mapping metadata /// Translator /// Primary state entry for this function (additional /// state entries can be added later, for instance for relationship navigation bindings) internal FunctionUpdateCommand(StorageFunctionMapping functionMapping, UpdateTranslator translator, IEntityStateEntry stateEntry) { EntityUtil.CheckArgumentNull(functionMapping, "functionMapping"); EntityUtil.CheckArgumentNull(translator, "translator"); EntityUtil.CheckArgumentNull(stateEntry, "stateEntry"); // populate the main state entry for error reporting m_stateEntries = new List(1); m_stateEntries.Add(stateEntry); // create a command DbCommandDefinition commandDefinition = translator.GenerateCommandDefinition(functionMapping); m_dbCommand = commandDefinition.CreateCommand(); } #endregion #region Fields private readonly List m_stateEntries; /// /// Gets the store command wrapped by this command. /// private readonly DbCommand m_dbCommand; ////// Gets pairs for column names and propagator results (so that we can associate reader results with /// the source records for server generated values). /// private List> m_resultColumns; /// /// Gets map from identifiers (key component proxies) to parameters holding the actual /// key values. Supports propagation of identifier values (fixup for server-gen keys) /// private List> m_inputIdentifiers; /// /// Gets map from identifiers (key component proxies) to column names producing the actual /// key values. Supports propagation of identifier values (fixup for server-gen keys) /// private Dictionarym_outputIdentifiers; /// /// Gets a reference to the rows affected output parameter for the stored procedure. May be null. /// private DbParameter m_rowsAffectedParameter; #endregion #region Properties internal override IEnumerableInputIdentifiers { get { if (null == m_inputIdentifiers) { yield break; } else { foreach (KeyValuePair inputIdentifier in m_inputIdentifiers) { yield return inputIdentifier.Key; } } } } internal override IEnumerable OutputIdentifiers { get { if (null == m_outputIdentifiers) { return Enumerable.Empty (); } return m_outputIdentifiers.Keys; } } internal override UpdateCommandKind Kind { get { return UpdateCommandKind.Function; } } #endregion #region Methods /// /// Gets state entries contributing to this function. Supports error reporting. /// internal override ListGetStateEntries(UpdateTranslator translator) { return m_stateEntries; } // Adds and register a DbParameter to the current command. internal void SetParameterValue(PropagatorResult result, StorageFunctionParameterBinding parameterBinding, UpdateTranslator translator) { // retrieve DbParameter DbParameter parameter = this.m_dbCommand.Parameters[parameterBinding.Parameter.Name]; parameter.Value = translator.KeyManager.GetPrincipalValue(result); // if the parameter corresponds to an identifier (key component), remember this fact in case // it's important for dependency ordering (e.g., output the identifier before creating it) long identifier = result.Identifier; if (PropagatorResult.NullIdentifier != identifier) { const int initialSize = 2; // expect on average less than two input identifiers per command if (null == m_inputIdentifiers) { m_inputIdentifiers = new List >(initialSize); } foreach (long principal in translator.KeyManager.GetPrincipals(identifier)) { m_inputIdentifiers.Add(new KeyValuePair (principal, parameter)); } // if there is a dependent state entry, remember that this command also handles the entry foreach (IEntityStateEntry stateEntry in translator.KeyManager.GetDependentStateEntries(identifier)) { m_stateEntries.Add(stateEntry); } } } // Adds and registers a DbParameter taking the number of rows affected internal void RegisterRowsAffectedParameter(FunctionParameter rowsAffectedParameter) { if (null != rowsAffectedParameter) { Debug.Assert(MetadataHelper.GetPrimitiveTypeKind(rowsAffectedParameter.TypeUsage) == PrimitiveTypeKind.Int32, "when loading mapping metadata, we check that the parameter is Int32"); Debug.Assert(rowsAffectedParameter.Mode == ParameterMode.Out, "when loading mapping metadata, we check that the parameter is an out parameter"); m_rowsAffectedParameter = m_dbCommand.Parameters[rowsAffectedParameter.Name]; } } // Registers a new state entry as part of the context for this command (for error reporting). internal void RegisterStateEntry(IEntityStateEntry stateEntry) { m_stateEntries.Add(EntityUtil.CheckArgumentNull(stateEntry, "stateEntry")); } // Adds a result column binding from a column name (from the result set for the function) to // a propagator result (which contains the context necessary to back-propagate the result). // If the result is an identifier, binds the internal void AddResultColumn(UpdateTranslator translator, String columnName, PropagatorResult result) { const int initializeSize = 2; // expect on average less than two result columns per command if (null == m_resultColumns) { m_resultColumns = new List >(initializeSize); } m_resultColumns.Add(new KeyValuePair (columnName, result)); long identifier = result.Identifier; if (PropagatorResult.NullIdentifier != identifier) { if (translator.KeyManager.HasPrincipals(identifier)) { throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.Update_GeneratedDependent(columnName)); } // register output identifier to enable fix-up and dependency tracking AddOutputIdentifier(columnName, identifier); } } // Indicate that a column in the command result set (specified by 'columnName') produces the // value for a key component (specified by 'identifier') private void AddOutputIdentifier(String columnName, Int64 identifier) { const int initialSize = 2; // expect on average less than two identifier output per command if (null == m_outputIdentifiers) { m_outputIdentifiers = new Dictionary (initialSize); } m_outputIdentifiers[identifier] = columnName; } // efects: Executes the current function command in the given transaction and connection context. // All server-generated values are added to the generatedValues list. If those values are identifiers, they are // also added to the identifierValues dictionary, which associates proxy identifiers for keys in the session // with their actual values, permitting fix-up of identifiers across relationships. internal override int Execute(UpdateTranslator translator, EntityConnection connection, Dictionary identifierValues, List > generatedValues) { // configure command to use the connection and transaction for this session m_dbCommand.Transaction = ((null != connection.CurrentTransaction) ? connection.CurrentTransaction.StoreTransaction : null); m_dbCommand.Connection = connection.StoreConnection; if (translator.CommandTimeout.HasValue) { m_dbCommand.CommandTimeout = translator.CommandTimeout.Value; } // set all identifier inputs (to support propagation of identifier values across relationship // boundaries) if (null != m_inputIdentifiers) { foreach (KeyValuePair inputIdentifier in m_inputIdentifiers) { object value; if (identifierValues.TryGetValue(inputIdentifier.Key, out value)) { // set the actual value for the identifier if it has been produced by some // other command inputIdentifier.Value.Value = value; } } } // Execute the query int rowsAffected; if (null != m_resultColumns) { // If there are result columns, read the server gen results rowsAffected = 0; using (DbDataReader reader = m_dbCommand.ExecuteReader(CommandBehavior.SequentialAccess)) { // Retrieve only the first row from the first result set if (reader.Read()) { rowsAffected++; foreach (var resultColumn in m_resultColumns .Select(r => new KeyValuePair (GetColumnOrdinal(translator, reader, r.Key), r.Value)) .OrderBy(r => r.Key)) // order by column ordinal to avoid breaking SequentialAccess readers { int columnOrdinal = resultColumn.Key; object value = reader.GetValue(columnOrdinal); // register for back-propagation PropagatorResult result = resultColumn.Value; generatedValues.Add(new KeyValuePair (result, value)); // register identifier if it exists Int64 identifier = result.Identifier; if (PropagatorResult.NullIdentifier != identifier) { identifierValues.Add(identifier, value); } } } // Consume the current reader (and subsequent result sets) so that any errors // executing the function can be intercepted CommandHelper.ConsumeReader(reader); } } else { rowsAffected = m_dbCommand.ExecuteNonQuery(); } // if an explicit rows affected parameter exists, use this value instead if (null != m_rowsAffectedParameter) { // by design, negative row counts indicate failure iff. an explicit rows // affected parameter is used if (DBNull.Value.Equals(m_rowsAffectedParameter.Value)) { rowsAffected = 0; } else { try { rowsAffected = Convert.ToInt32(m_rowsAffectedParameter.Value, CultureInfo.InvariantCulture); } catch (Exception e) { if (UpdateTranslator.RequiresContext(e)) { // wrap the exception throw EntityUtil.Update(System.Data.Entity.Strings.Update_UnableToConvertRowsAffectedParameterToInt32( m_rowsAffectedParameter.ParameterName, typeof(int).FullName), e, this.GetStateEntries(translator)); } throw; } } } return rowsAffected; } private int GetColumnOrdinal(UpdateTranslator translator, DbDataReader reader, string columnName) { int columnOrdinal; try { columnOrdinal = reader.GetOrdinal(columnName); } catch (IndexOutOfRangeException) { throw EntityUtil.Update(System.Data.Entity.Strings.Update_MissingResultColumn(columnName), null, this.GetStateEntries(translator)); } return columnOrdinal; } internal override int CompareToType(UpdateCommand otherCommand) { Debug.Assert(!object.ReferenceEquals(this, otherCommand), "caller should ensure other command is different"); FunctionUpdateCommand other = (FunctionUpdateCommand)otherCommand; // first state entry is the 'main' state entry for the command (see ctor) IEntityStateEntry thisParent = this.m_stateEntries[0]; IEntityStateEntry otherParent = other.m_stateEntries[0]; // order by state int result = (int)thisParent.State - (int)otherParent.State; if (0 != result) { return result; } // order by entity set result = StringComparer.Ordinal.Compare(thisParent.EntitySet.Name, otherParent.EntitySet.Name); if (0 != result) { return result; } result = StringComparer.Ordinal.Compare(thisParent.EntitySet.EntityContainer.Name, otherParent.EntitySet.EntityContainer.Name); if (0 != result) { return result; } // order by key values int thisInputIdentifierCount = (null == this.m_inputIdentifiers ? 0 : this.m_inputIdentifiers.Count); int otherInputIdentifierCount = (null == other.m_inputIdentifiers ? 0 : other.m_inputIdentifiers.Count); result = thisInputIdentifierCount - otherInputIdentifierCount; if (0 != result) { return result; } for (int i = 0; i < thisInputIdentifierCount; i++) { DbParameter thisParameter = this.m_inputIdentifiers[i].Value; DbParameter otherParameter = other.m_inputIdentifiers[i].Value; result = Comparer
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- EncodingFallbackAwareXmlTextWriter.cs
- ApplicationInfo.cs
- MarkupProperty.cs
- ValidateNames.cs
- ContextMenuAutomationPeer.cs
- SchemaMerger.cs
- HttpResponseHeader.cs
- EntityContainerEntitySet.cs
- SqlTransaction.cs
- Point.cs
- LocalizableResourceBuilder.cs
- CommandPlan.cs
- SelectedDatesCollection.cs
- DataSourceCache.cs
- DispatcherExceptionEventArgs.cs
- SaveFileDialog.cs
- PasswordBoxAutomationPeer.cs
- StyleHelper.cs
- ProxyGenerationError.cs
- GlyphManager.cs
- ParserExtension.cs
- ParameterBuilder.cs
- DataKeyArray.cs
- NameObjectCollectionBase.cs
- QilName.cs
- ThemeDirectoryCompiler.cs
- NullExtension.cs
- UserNameSecurityTokenAuthenticator.cs
- EventsTab.cs
- SessionMode.cs
- PageTheme.cs
- ISAPIApplicationHost.cs
- RecipientInfo.cs
- ObsoleteAttribute.cs
- DiscardableAttribute.cs
- SystemIcons.cs
- DataBoundControlHelper.cs
- ModelUtilities.cs
- TreeSet.cs
- DataControlLinkButton.cs
- ECDiffieHellmanCng.cs
- XDRSchema.cs
- DbMetaDataFactory.cs
- PrintPageEvent.cs
- TabletDevice.cs
- StsCommunicationException.cs
- MultiBindingExpression.cs
- ArglessEventHandlerProxy.cs
- MappingModelBuildProvider.cs
- FrameworkReadOnlyPropertyMetadata.cs
- TimersDescriptionAttribute.cs
- TypedMessageConverter.cs
- FunctionNode.cs
- ByteFacetDescriptionElement.cs
- CodeMemberMethod.cs
- CommandLibraryHelper.cs
- DependentTransaction.cs
- UnlockInstanceAsyncResult.cs
- ISO2022Encoding.cs
- BaseTemplateParser.cs
- EntitySqlQueryCacheKey.cs
- ConnectionPoolManager.cs
- InternalPermissions.cs
- ParameterModifier.cs
- MessageEnumerator.cs
- FindCriteriaElement.cs
- SQLInt64Storage.cs
- SqlHelper.cs
- FreezableDefaultValueFactory.cs
- ListSortDescriptionCollection.cs
- NavigationPropertyEmitter.cs
- SqlErrorCollection.cs
- VisualTreeUtils.cs
- DataObjectSettingDataEventArgs.cs
- httpserverutility.cs
- ErrorsHelper.cs
- ObjectReaderCompiler.cs
- VirtualizingPanel.cs
- MdbDataFileEditor.cs
- XmlWhitespace.cs
- CipherData.cs
- XamlInt32CollectionSerializer.cs
- URLIdentityPermission.cs
- ViewValidator.cs
- Publisher.cs
- MemoryStream.cs
- NavigationService.cs
- TcpStreams.cs
- GlobalizationSection.cs
- TextSegment.cs
- FormViewUpdateEventArgs.cs
- DrawListViewSubItemEventArgs.cs
- HtmlHistory.cs
- ProtectedConfigurationSection.cs
- StringExpressionSet.cs
- ModuleElement.cs
- NamespaceMapping.cs
- RegexWriter.cs
- ComponentConverter.cs
- InternalConfigHost.cs