Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Map / Update / Internal / UpdateCommand.cs / 1305376 / UpdateCommand.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Data.Metadata.Edm; using System.Data.Common; using System.Collections.Generic; using System.Text; using System.Diagnostics; using System.Globalization; using System.Data.Common.Utils; using System.Data.Common.CommandTrees; using System.Data.Objects; using System.Linq; using System.Data.EntityClient; using System.Threading; namespace System.Data.Mapping.Update.Internal { internal enum UpdateCommandKind { Dynamic, Function, } ////// Class storing the result of compiling an instance DML command. /// internal abstract class UpdateCommand : IComparable, IEquatable { protected UpdateCommand(PropagatorResult originalValues, PropagatorResult currentValues) { m_originalValues = originalValues; m_currentValues = currentValues; } private readonly PropagatorResult m_originalValues; private readonly PropagatorResult m_currentValues; // When it is not possible to order two commands based on their contents, we assign an 'ordering identifier' // so that one will consistently precede the other. private static int s_orderingIdentifierCounter; private int m_orderingIdentifier; /// /// Gets all identifiers (key values basically) generated by this command. For instance, /// @@IDENTITY values. /// internal abstract IEnumerableOutputIdentifiers { get; } /// /// Gets all identifiers required by this command. /// internal abstract IEnumerableInputIdentifiers { get; } /// /// Gets table (if any) associated with the current command. FunctionUpdateCommand has no table. /// internal virtual EntitySet Table { get { return null; } } ////// Gets type of command. /// internal abstract UpdateCommandKind Kind { get; } ////// Gets original values of row/entity handled by this command. /// internal PropagatorResult OriginalValues { get { return m_originalValues; } } ////// Gets current values of row/entity handled by this command. /// internal PropagatorResult CurrentValues { get { return m_currentValues; } } ////// Yields all state entries contributing to this command. Used for error reporting. /// /// Translator context. ///Related state entries. internal abstract IListGetStateEntries(UpdateTranslator translator); /// /// Determines model level dependencies for the current command. Dependencies are based /// on the model operations performed by the command (adding or deleting entities or relationships). /// internal void GetRequiredAndProducedEntities(UpdateTranslator translator, KeyToListMapaddedEntities, KeyToListMap deletedEntities, KeyToListMap addedRelationships, KeyToListMap deletedRelationships) { IList stateEntries = GetStateEntries(translator); foreach (IEntityStateEntry stateEntry in stateEntries) { if (!stateEntry.IsRelationship) { if (stateEntry.State == EntityState.Added) { addedEntities.Add(stateEntry.EntityKey, this); } else if (stateEntry.State == EntityState.Deleted) { deletedEntities.Add(stateEntry.EntityKey, this); } } } // process foreign keys if (null != this.OriginalValues) { // if a foreign key being deleted, it 'frees' or 'produces' the referenced key AddReferencedEntities(translator, this.OriginalValues, deletedRelationships); } if (null != this.CurrentValues) { // if a foreign key is being added, if requires the referenced key AddReferencedEntities(translator, this.CurrentValues, addedRelationships); } // process relationships foreach (IEntityStateEntry stateEntry in stateEntries) { if (stateEntry.IsRelationship) { // only worry about the relationship if it is being added or deleted bool isAdded = stateEntry.State == EntityState.Added; if (isAdded || stateEntry.State == EntityState.Deleted) { DbDataRecord record = isAdded ? (DbDataRecord)stateEntry.CurrentValues : stateEntry.OriginalValues; Debug.Assert(2 == record.FieldCount, "non-binary relationship?"); EntityKey end1 = (EntityKey)record[0]; EntityKey end2 = (EntityKey)record[1]; // relationships require the entity when they're added and free the entity when they're deleted... KeyToListMap affected = isAdded ? addedRelationships : deletedRelationships; // both ends are being modified by the relationship affected.Add(end1, this); affected.Add(end2, this); } } } } private void AddReferencedEntities(UpdateTranslator translator, PropagatorResult result, KeyToListMap referencedEntities) { foreach (PropagatorResult property in result.GetMemberValues()) { if (property.IsSimple && property.Identifier != PropagatorResult.NullIdentifier && (PropagatorFlags.ForeignKey == (property.PropagatorFlags & PropagatorFlags.ForeignKey))) { foreach (int principal in translator.KeyManager.GetPrincipals(property.Identifier)) { PropagatorResult owner; if (translator.KeyManager.TryGetIdentifierOwner(principal, out owner) && null != owner.StateEntry) { Debug.Assert(!owner.StateEntry.IsRelationship, "owner must not be a relationship"); referencedEntities.Add(owner.StateEntry.EntityKey, this); } } } } } /// /// Executes the current update command. /// /// Translator context. /// EntityConnection to use (and implicitly, the EntityTransaction to use). /// Aggregator for identifier values (read for InputIdentifiers; write for /// OutputIdentifiers /// Aggregator for server generated values. ///Number of rows affected by the command. internal abstract long Execute(UpdateTranslator translator, EntityConnection connection, DictionaryidentifierValues, List > generatedValues); /// /// Implementation of CompareTo for concrete subclass of UpdateCommand. /// internal abstract int CompareToType(UpdateCommand other); ////// Provides a suggested ordering between two commands. Ensuring a consistent ordering is important to avoid deadlocks /// between two clients because it means locks are acquired in the same order where possible. The ordering criteria are as /// follows (and are partly implemented in the CompareToType method). In some cases there are specific secondary /// reasons for the order (e.g. operator kind), but for the most case we just care that a consistent ordering /// is applied: /// /// - The kind of command (dynamic or function). This is an arbitrary criteria. /// - The kind of operator (insert, update, delete). See public int CompareTo(UpdateCommand other) { // If the commands are the same (by reference), return 0 immediately. Otherwise, we try to find (and eventually // force) an ordering between them by returning a value that is non-zero. if (this.Equals(other)) { return 0; } Debug.Assert(null != other, "comparing to null UpdateCommand"); int result = (int)this.Kind - (int)other.Kind; if (0 != result) { return result; } // defer to specific type for other comparisons... result = CompareToType(other); if (0 != result) { return result; } // if the commands are indistinguishable, assign arbitrary identifiers to them to ensure consistent ordering unchecked { if (this.m_orderingIdentifier == 0) { this.m_orderingIdentifier = Interlocked.Increment(ref s_orderingIdentifierCounter); } if (other.m_orderingIdentifier == 0) { other.m_orderingIdentifier = Interlocked.Increment(ref s_orderingIdentifierCounter); } return this.m_orderingIdentifier - other.m_orderingIdentifier; } } #region IEquatable: note that we use reference equality public bool Equals(UpdateCommand other) { return base.Equals(other); } public override bool Equals(object obj) { return base.Equals(obj); } public override int GetHashCode() { return base.GetHashCode(); } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- //for details of the ordering. /// - The target of the modification (table for dynamic, set for function). /// - Primary key for the modification (table key for dynamic, entity keys for function). /// /// If it is not possible to differentiate between two commands (e.g., where the user is inserting entities with server-generated /// primary keys and has not given explicit values), arbitrary ordering identifiers are assigned to the commands to /// ensure CompareTo is well-behaved (doesn't return 0 for different commands and suggests consistent ordering). /// // Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Data.Metadata.Edm; using System.Data.Common; using System.Collections.Generic; using System.Text; using System.Diagnostics; using System.Globalization; using System.Data.Common.Utils; using System.Data.Common.CommandTrees; using System.Data.Objects; using System.Linq; using System.Data.EntityClient; using System.Threading; namespace System.Data.Mapping.Update.Internal { internal enum UpdateCommandKind { Dynamic, Function, } ////// Class storing the result of compiling an instance DML command. /// internal abstract class UpdateCommand : IComparable, IEquatable { protected UpdateCommand(PropagatorResult originalValues, PropagatorResult currentValues) { m_originalValues = originalValues; m_currentValues = currentValues; } private readonly PropagatorResult m_originalValues; private readonly PropagatorResult m_currentValues; // When it is not possible to order two commands based on their contents, we assign an 'ordering identifier' // so that one will consistently precede the other. private static int s_orderingIdentifierCounter; private int m_orderingIdentifier; /// /// Gets all identifiers (key values basically) generated by this command. For instance, /// @@IDENTITY values. /// internal abstract IEnumerableOutputIdentifiers { get; } /// /// Gets all identifiers required by this command. /// internal abstract IEnumerableInputIdentifiers { get; } /// /// Gets table (if any) associated with the current command. FunctionUpdateCommand has no table. /// internal virtual EntitySet Table { get { return null; } } ////// Gets type of command. /// internal abstract UpdateCommandKind Kind { get; } ////// Gets original values of row/entity handled by this command. /// internal PropagatorResult OriginalValues { get { return m_originalValues; } } ////// Gets current values of row/entity handled by this command. /// internal PropagatorResult CurrentValues { get { return m_currentValues; } } ////// Yields all state entries contributing to this command. Used for error reporting. /// /// Translator context. ///Related state entries. internal abstract IListGetStateEntries(UpdateTranslator translator); /// /// Determines model level dependencies for the current command. Dependencies are based /// on the model operations performed by the command (adding or deleting entities or relationships). /// internal void GetRequiredAndProducedEntities(UpdateTranslator translator, KeyToListMapaddedEntities, KeyToListMap deletedEntities, KeyToListMap addedRelationships, KeyToListMap deletedRelationships) { IList stateEntries = GetStateEntries(translator); foreach (IEntityStateEntry stateEntry in stateEntries) { if (!stateEntry.IsRelationship) { if (stateEntry.State == EntityState.Added) { addedEntities.Add(stateEntry.EntityKey, this); } else if (stateEntry.State == EntityState.Deleted) { deletedEntities.Add(stateEntry.EntityKey, this); } } } // process foreign keys if (null != this.OriginalValues) { // if a foreign key being deleted, it 'frees' or 'produces' the referenced key AddReferencedEntities(translator, this.OriginalValues, deletedRelationships); } if (null != this.CurrentValues) { // if a foreign key is being added, if requires the referenced key AddReferencedEntities(translator, this.CurrentValues, addedRelationships); } // process relationships foreach (IEntityStateEntry stateEntry in stateEntries) { if (stateEntry.IsRelationship) { // only worry about the relationship if it is being added or deleted bool isAdded = stateEntry.State == EntityState.Added; if (isAdded || stateEntry.State == EntityState.Deleted) { DbDataRecord record = isAdded ? (DbDataRecord)stateEntry.CurrentValues : stateEntry.OriginalValues; Debug.Assert(2 == record.FieldCount, "non-binary relationship?"); EntityKey end1 = (EntityKey)record[0]; EntityKey end2 = (EntityKey)record[1]; // relationships require the entity when they're added and free the entity when they're deleted... KeyToListMap affected = isAdded ? addedRelationships : deletedRelationships; // both ends are being modified by the relationship affected.Add(end1, this); affected.Add(end2, this); } } } } private void AddReferencedEntities(UpdateTranslator translator, PropagatorResult result, KeyToListMap referencedEntities) { foreach (PropagatorResult property in result.GetMemberValues()) { if (property.IsSimple && property.Identifier != PropagatorResult.NullIdentifier && (PropagatorFlags.ForeignKey == (property.PropagatorFlags & PropagatorFlags.ForeignKey))) { foreach (int principal in translator.KeyManager.GetPrincipals(property.Identifier)) { PropagatorResult owner; if (translator.KeyManager.TryGetIdentifierOwner(principal, out owner) && null != owner.StateEntry) { Debug.Assert(!owner.StateEntry.IsRelationship, "owner must not be a relationship"); referencedEntities.Add(owner.StateEntry.EntityKey, this); } } } } } /// /// Executes the current update command. /// /// Translator context. /// EntityConnection to use (and implicitly, the EntityTransaction to use). /// Aggregator for identifier values (read for InputIdentifiers; write for /// OutputIdentifiers /// Aggregator for server generated values. ///Number of rows affected by the command. internal abstract long Execute(UpdateTranslator translator, EntityConnection connection, DictionaryidentifierValues, List > generatedValues); /// /// Implementation of CompareTo for concrete subclass of UpdateCommand. /// internal abstract int CompareToType(UpdateCommand other); ////// Provides a suggested ordering between two commands. Ensuring a consistent ordering is important to avoid deadlocks /// between two clients because it means locks are acquired in the same order where possible. The ordering criteria are as /// follows (and are partly implemented in the CompareToType method). In some cases there are specific secondary /// reasons for the order (e.g. operator kind), but for the most case we just care that a consistent ordering /// is applied: /// /// - The kind of command (dynamic or function). This is an arbitrary criteria. /// - The kind of operator (insert, update, delete). See public int CompareTo(UpdateCommand other) { // If the commands are the same (by reference), return 0 immediately. Otherwise, we try to find (and eventually // force) an ordering between them by returning a value that is non-zero. if (this.Equals(other)) { return 0; } Debug.Assert(null != other, "comparing to null UpdateCommand"); int result = (int)this.Kind - (int)other.Kind; if (0 != result) { return result; } // defer to specific type for other comparisons... result = CompareToType(other); if (0 != result) { return result; } // if the commands are indistinguishable, assign arbitrary identifiers to them to ensure consistent ordering unchecked { if (this.m_orderingIdentifier == 0) { this.m_orderingIdentifier = Interlocked.Increment(ref s_orderingIdentifierCounter); } if (other.m_orderingIdentifier == 0) { other.m_orderingIdentifier = Interlocked.Increment(ref s_orderingIdentifierCounter); } return this.m_orderingIdentifier - other.m_orderingIdentifier; } } #region IEquatable: note that we use reference equality public bool Equals(UpdateCommand other) { return base.Equals(other); } public override bool Equals(object obj) { return base.Equals(obj); } public override int GetHashCode() { return base.GetHashCode(); } #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.for details of the ordering. /// - The target of the modification (table for dynamic, set for function). /// - Primary key for the modification (table key for dynamic, entity keys for function). /// /// If it is not possible to differentiate between two commands (e.g., where the user is inserting entities with server-generated /// primary keys and has not given explicit values), arbitrary ordering identifiers are assigned to the commands to /// ensure CompareTo is well-behaved (doesn't return 0 for different commands and suggests consistent ordering). ///
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Regex.cs
- NullRuntimeConfig.cs
- Util.cs
- XmlWriterTraceListener.cs
- WebReferenceCollection.cs
- Composition.cs
- RangeValuePatternIdentifiers.cs
- FileDialogCustomPlace.cs
- ResolveInfo.cs
- TreeNodeBinding.cs
- DWriteFactory.cs
- WmlControlAdapter.cs
- StateDesignerConnector.cs
- SymbolEqualComparer.cs
- DataBoundControlAdapter.cs
- CommandID.cs
- SettingsSavedEventArgs.cs
- RestHandlerFactory.cs
- MimeTextImporter.cs
- WasEndpointConfigContainer.cs
- BufferedGraphicsManager.cs
- PageContent.cs
- OverlappedAsyncResult.cs
- TableRowGroup.cs
- EllipseGeometry.cs
- FusionWrap.cs
- PrimitiveOperationFormatter.cs
- EntityDataSourceDesigner.cs
- Speller.cs
- COM2ColorConverter.cs
- InfoCardRSAPKCS1SignatureDeformatter.cs
- PointAnimationClockResource.cs
- SByte.cs
- LoadRetryHandler.cs
- WebPartCancelEventArgs.cs
- UnsafePeerToPeerMethods.cs
- Exceptions.cs
- NullRuntimeConfig.cs
- SoapSchemaMember.cs
- AccessedThroughPropertyAttribute.cs
- ElementProxy.cs
- DelegatingConfigHost.cs
- KeyGesture.cs
- HttpGetProtocolReflector.cs
- TextDecorationUnitValidation.cs
- ASCIIEncoding.cs
- QfeChecker.cs
- NodeFunctions.cs
- CurrentChangedEventManager.cs
- OneOfScalarConst.cs
- AtomEntry.cs
- DetailsViewUpdateEventArgs.cs
- SecurityTokenException.cs
- PixelFormatConverter.cs
- IsolatedStorageFileStream.cs
- WebUtil.cs
- HierarchicalDataBoundControlAdapter.cs
- Encoder.cs
- CounterCreationDataCollection.cs
- AdornerPresentationContext.cs
- LinqExpressionNormalizer.cs
- IgnoreFlushAndCloseStream.cs
- AssemblyNameProxy.cs
- DataGridViewCellStyleConverter.cs
- UpdateCommandGenerator.cs
- ExpressionBindings.cs
- RoutedEventHandlerInfo.cs
- ChannelEndpointElementCollection.cs
- OpenTypeCommon.cs
- SqlRecordBuffer.cs
- ACE.cs
- UpdatePanelTrigger.cs
- PrintingPermission.cs
- QuaternionRotation3D.cs
- SerializationFieldInfo.cs
- BaseDataBoundControl.cs
- Label.cs
- HtmlInputPassword.cs
- CursorInteropHelper.cs
- InternalBase.cs
- DbDataRecord.cs
- MobileUserControl.cs
- PermissionAttributes.cs
- TriggerAction.cs
- Literal.cs
- WebPermission.cs
- DurationConverter.cs
- VectorAnimation.cs
- NativeMethods.cs
- ParameterBuilder.cs
- RectangleConverter.cs
- SHA384Managed.cs
- X509PeerCertificateAuthenticationElement.cs
- ConfigXmlText.cs
- ThaiBuddhistCalendar.cs
- ThemeableAttribute.cs
- MarkupExtensionReturnTypeAttribute.cs
- FontStyle.cs
- MimeTypePropertyAttribute.cs
- TypeElement.cs