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
- BezierSegment.cs
- PermissionListSet.cs
- ChildTable.cs
- ExtractorMetadata.cs
- XmlNode.cs
- CompilerScope.Storage.cs
- WebResourceAttribute.cs
- FlowDocumentReader.cs
- AnnotationObservableCollection.cs
- ArcSegment.cs
- GridItemPattern.cs
- SkewTransform.cs
- XmlILConstructAnalyzer.cs
- AnalyzedTree.cs
- EdmConstants.cs
- ConfigXmlElement.cs
- CaseInsensitiveOrdinalStringComparer.cs
- DataGridCommandEventArgs.cs
- XPathItem.cs
- StackOverflowException.cs
- ExpressionConverter.cs
- DeferredReference.cs
- XmlLoader.cs
- ProfileServiceManager.cs
- DependencyPropertyValueSerializer.cs
- RequestResizeEvent.cs
- PrincipalPermission.cs
- ADMembershipProvider.cs
- Shape.cs
- StrongTypingException.cs
- LockedActivityGlyph.cs
- ProxyHwnd.cs
- RsaElement.cs
- DrawingGroup.cs
- PersonalizationStateInfoCollection.cs
- ParsedAttributeCollection.cs
- PixelFormatConverter.cs
- BaseComponentEditor.cs
- CellTreeSimplifier.cs
- _CacheStreams.cs
- CompositeClientFormatter.cs
- TreeViewEvent.cs
- OLEDB_Enum.cs
- XmlSchemaAttribute.cs
- ContentElement.cs
- login.cs
- IdentitySection.cs
- MetadataSection.cs
- CheckBoxPopupAdapter.cs
- PrintControllerWithStatusDialog.cs
- ItemTypeToolStripMenuItem.cs
- AutomationElement.cs
- ColorContext.cs
- DocumentsTrace.cs
- SecurityException.cs
- SQLDateTimeStorage.cs
- CompiledXpathExpr.cs
- QueryTaskGroupState.cs
- ErrorRuntimeConfig.cs
- SamlConditions.cs
- TransactionFlowProperty.cs
- XmlDomTextWriter.cs
- FilteredAttributeCollection.cs
- TraversalRequest.cs
- SecurityRuntime.cs
- WebPartVerb.cs
- SqlBinder.cs
- CodeValidator.cs
- ToolBarOverflowPanel.cs
- BooleanToVisibilityConverter.cs
- DataGridView.cs
- PropertyBuilder.cs
- CanExecuteRoutedEventArgs.cs
- CompressEmulationStream.cs
- GACMembershipCondition.cs
- EmbossBitmapEffect.cs
- XXXInfos.cs
- TypeConverter.cs
- DrawListViewItemEventArgs.cs
- BuildResult.cs
- FormsAuthenticationEventArgs.cs
- InternalUserCancelledException.cs
- DetailsViewUpdatedEventArgs.cs
- ApplicationDirectory.cs
- BitmapMetadataBlob.cs
- ViewBase.cs
- ReceiveErrorHandling.cs
- PenContext.cs
- _LazyAsyncResult.cs
- updatecommandorderer.cs
- InternalPermissions.cs
- FunctionUpdateCommand.cs
- RouteValueExpressionBuilder.cs
- DbQueryCommandTree.cs
- TextureBrush.cs
- GridViewUpdatedEventArgs.cs
- TextAction.cs
- RuntimeHelpers.cs
- AppModelKnownContentFactory.cs
- InputGestureCollection.cs