Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataEntity / System / Data / Map / Update / Internal / FunctionUpdateCommand.cs / 4 / 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
- ProfileBuildProvider.cs
- DbDataSourceEnumerator.cs
- DataGridCommandEventArgs.cs
- BaseCAMarshaler.cs
- OleAutBinder.cs
- IPPacketInformation.cs
- FacetDescriptionElement.cs
- MasterPage.cs
- BrowserDefinition.cs
- PanelStyle.cs
- ImportCatalogPart.cs
- LinqDataSourceDisposeEventArgs.cs
- shaper.cs
- LineInfo.cs
- XmlElementAttribute.cs
- RelationalExpressions.cs
- ShaderEffect.cs
- HttpFormatExtensions.cs
- JsonEncodingStreamWrapper.cs
- DocumentReference.cs
- CatalogZoneBase.cs
- OuterGlowBitmapEffect.cs
- PropertyToken.cs
- HelpOperationInvoker.cs
- regiisutil.cs
- DataRecordInfo.cs
- CodeObject.cs
- SystemSounds.cs
- TimersDescriptionAttribute.cs
- SettingsPropertyIsReadOnlyException.cs
- TreeIterators.cs
- ProfileService.cs
- XmlDigitalSignatureProcessor.cs
- DynamicValidatorEventArgs.cs
- DataBinding.cs
- TypeGeneratedEventArgs.cs
- XsdDuration.cs
- GeneralTransform.cs
- ContextMenu.cs
- x509utils.cs
- StandardToolWindows.cs
- PartialClassGenerationTaskInternal.cs
- DataServiceProcessingPipeline.cs
- OperationAbortedException.cs
- FixedFlowMap.cs
- DoubleAnimation.cs
- ArrangedElementCollection.cs
- GeometryGroup.cs
- HttpCachePolicyWrapper.cs
- PrintPreviewDialog.cs
- DropShadowEffect.cs
- SplineKeyFrames.cs
- ToolStripLabel.cs
- SQlBooleanStorage.cs
- QilStrConcatenator.cs
- ValidationErrorCollection.cs
- Win32Native.cs
- SqlDataSourceQuery.cs
- TableDetailsCollection.cs
- SynchronizedDispatch.cs
- Win32KeyboardDevice.cs
- Visual.cs
- PaintValueEventArgs.cs
- TextSelection.cs
- ServiceElementCollection.cs
- MultilineStringConverter.cs
- BitmapDecoder.cs
- PrimitiveCodeDomSerializer.cs
- MobileDeviceCapabilitiesSectionHandler.cs
- ListViewItem.cs
- SelectionItemProviderWrapper.cs
- future.cs
- ProfileGroupSettingsCollection.cs
- TagMapInfo.cs
- MimeObjectFactory.cs
- BooleanSwitch.cs
- ValuePattern.cs
- PeerContact.cs
- ServiceMemoryGates.cs
- SimpleWebHandlerParser.cs
- ExpressionLink.cs
- NetworkStream.cs
- EventDescriptor.cs
- DetailsViewInsertedEventArgs.cs
- WinEventTracker.cs
- SoapSchemaMember.cs
- PropertyPathWorker.cs
- ArrayTypeMismatchException.cs
- PathSegment.cs
- RoutedEvent.cs
- HashSet.cs
- KoreanLunisolarCalendar.cs
- WindowCollection.cs
- GeneralTransform3DTo2D.cs
- ProcessHostMapPath.cs
- XmlElementCollection.cs
- DataGridPagerStyle.cs
- CopyNamespacesAction.cs
- RegistrationServices.cs
- StackBuilderSink.cs