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 / updatecommandorderer.cs / 1 / updatecommandorderer.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Collections.Generic; using System.Data.Common.Utils; using System.Data.Metadata.Edm; using System.Linq; using System.Diagnostics; namespace System.Data.Mapping.Update.Internal { internal class UpdateCommandOrderer : Graph{ /// /// Gets comparer used to resolve identifiers to actual 'owning' key values (e.g. across referential constraints) /// private readonly ForeignKeyValueComparer _keyComparer; ////// Maps from tables to all "source" referential constraints (where the table declares /// foreign keys) /// private readonly KeyToListMap_sourceMap; /// /// Maps from tables to all "target" referential constraints (where the table is /// referenced by a foreign key) /// private readonly KeyToListMap_targetMap; /// /// Tracks whether any function commands exist in the current payload. /// private readonly bool _hasFunctionCommands; ////// Gets translator producing this graph. /// private readonly UpdateTranslator _translator; internal UpdateCommandOrderer(IEnumerablecommands, UpdateTranslator translator) : base(EqualityComparer .Default) { _translator = translator; _keyComparer = new ForeignKeyValueComparer(_translator.KeyComparer); HashSet tables = new HashSet (); HashSet containers = new HashSet (); // add all vertices (one vertex for every command) foreach (UpdateCommand command in commands) { if (null != command.Table) { tables.Add(command.Table); containers.Add(command.Table.EntityContainer); } AddVertex(command); if (command.Kind == UpdateCommandKind.Function) { _hasFunctionCommands = true; } } // figure out which foreign keys are interesting in this scope InitializeForeignKeyMaps(containers, tables, out _sourceMap, out _targetMap); // add edges for each ordering dependency amongst the commands AddServerGenDependencies(); AddForeignKeyDependencies(); if (_hasFunctionCommands) { AddModelDependencies(); } } private static void InitializeForeignKeyMaps(HashSet containers, HashSet tables, out KeyToListMap sourceMap, out KeyToListMap targetMap) { sourceMap = new KeyToListMap (EqualityComparer .Default); targetMap = new KeyToListMap (EqualityComparer .Default); // Retrieve relationship ends from each container to populate edges in dependency // graph foreach (EntityContainer container in containers) { foreach (EntitySetBase extent in container.BaseEntitySets) { AssociationSet associationSet = extent as AssociationSet; if (null != associationSet) { AssociationSetEnd source = null; AssociationSetEnd target = null; var ends = associationSet.AssociationSetEnds; if (2 == ends.Count) { // source is equivalent to the "to" end of relationship, target is "from" AssociationType associationType = associationSet.ElementType; bool constraintFound = false; ReferentialConstraint fkConstraint = null; foreach (ReferentialConstraint constraint in associationType.ReferentialConstraints) { if (constraintFound) { Debug.Fail("relationship set should have at most one constraint"); } else { constraintFound = true; } source = associationSet.AssociationSetEnds[constraint.ToRole.Name]; target = associationSet.AssociationSetEnds[constraint.FromRole.Name]; fkConstraint = constraint; } Debug.Assert(constraintFound && null != target && null != source, "relationship set must have at least one constraint"); // only understand binary (foreign key) relationships between entity sets if (null != target && null != source) { if (tables.Contains(target.EntitySet)&& tables.Contains(source.EntitySet)) { // Remember metadata sourceMap.Add(source.EntitySet, fkConstraint); targetMap.Add(target.EntitySet, fkConstraint); } } } } } } } // Adds edges to dependency graph for server-generated values. // // Determines which commands produce identifiers (key components) and which commands // consume them. Producers are potentially edge predecessors and consumers are potentially // edge successors. The command objects report the identifiers they produce (OutputIdentifiers) // and the identifiers they consume (InputIdentifiers) private void AddServerGenDependencies() { // Identify all "shared" output parameters (e.g., SQL Server identifiers) Dictionary predecessors = new Dictionary (); foreach (UpdateCommand command in this.Vertices) { foreach (Int64 output in command.OutputIdentifiers) { try { predecessors.Add(output, command); } catch (ArgumentException duplicateKey) { // throw an exception indicating that a key value is generated in two locations // in the store throw EntityUtil.Update(System.Data.Entity.Strings.Update_AmbiguousServerGenIdentifier, duplicateKey, command.GetStateEntries(_translator)); } } } // Identify all dependent input parameters foreach (UpdateCommand command in this.Vertices) { foreach (Int64 input in command.InputIdentifiers) { UpdateCommand from; if (predecessors.TryGetValue(input, out from)) { AddEdge(from, command); } } } } // Adds edges to dependency graph based on foreign keys. private void AddForeignKeyDependencies() { KeyToListMap predecessors = DetermineForeignKeyPredecessors(); AddForeignKeyEdges(predecessors); } // Finds all successors to the given predecessors and registers the resulting dependency edges in this // graph. // // - Commands (updates or inserts) inserting FK "sources" (referencing foreign key) // - Commands (updates or deletes) deleting FK "targets" (referenced by the foreign key) // // To avoid violating constraints, FK references must be created before their referees, and // cannot be deleted before their references. private void AddForeignKeyEdges(KeyToListMap predecessors) { foreach (DynamicUpdateCommand command in this.Vertices.OfType ()) { // register all source successors if (ModificationOperator.Update == command.Operator || ModificationOperator.Insert == command.Operator) { foreach (ReferentialConstraint fkConstraint in _sourceMap.EnumerateValues(command.Table)) { ForeignKeyValue fk; if (ForeignKeyValue.TryCreateSourceKey(fkConstraint, command.CurrentValues, true, out fk)) { // if this is an update and the source key is unchanged, there is no // need to add a dependency (from the perspective of the target, the update // is a no-op) ForeignKeyValue originalFK; if (ModificationOperator.Update != command.Operator || !ForeignKeyValue.TryCreateSourceKey(fkConstraint, command.OriginalValues, true, out originalFK) || !_keyComparer.Equals(originalFK, fk)) { foreach (UpdateCommand predecessor in predecessors.EnumerateValues(fk)) { // don't add self-edges for FK dependencies, since a single operation // in the store is atomic if (predecessor != command) { AddEdge(predecessor, command); } } } } } } // register all target successors if (ModificationOperator.Update == command.Operator || ModificationOperator.Delete == command.Operator) { foreach (ReferentialConstraint fkConstraint in _targetMap.EnumerateValues(command.Table)) { ForeignKeyValue fk; if (ForeignKeyValue.TryCreateTargetKey(fkConstraint, command.OriginalValues, false, out fk)) { // if this is an update and the target key is unchanged, there is no // need to add a dependency (from the perspective of the source, the update // is a no-op) ForeignKeyValue currentFK; if (ModificationOperator.Update != command.Operator || !ForeignKeyValue.TryCreateTargetKey(fkConstraint, command.CurrentValues, false, out currentFK) || !_keyComparer.Equals(currentFK, fk)) { foreach (UpdateCommand predecessor in predecessors.EnumerateValues(fk)) { // don't add self-edges for FK dependencies, since a single operation // in the store is atomic if (predecessor != command) { AddEdge(predecessor, command); } } } } } } } } // Builds a map from foreign key instances to commands, with an entry for every command that may need to // precede some other operation. // // Predecessor commands must precede other commands using those values. There are two kinds of // predecessor: // // - Commands (updates or inserts) inserting FK "targets" (referenced by the foreign key) // - Commands (updates or deletes) deleting FK "sources" (referencing the foreign key) // // To avoid violating constraints, FK values must be created before they are referenced, and // cannot be deleted before their references private KeyToListMap DetermineForeignKeyPredecessors() { KeyToListMap predecessors = new KeyToListMap ( _keyComparer); foreach (DynamicUpdateCommand command in this.Vertices.OfType ()) { if (ModificationOperator.Update == command.Operator || ModificationOperator.Insert == command.Operator) { foreach (ReferentialConstraint fkConstraint in _targetMap.EnumerateValues(command.Table)) { ForeignKeyValue fk; if (ForeignKeyValue.TryCreateTargetKey(fkConstraint, command.CurrentValues, true, out fk)) { // if this is an update and the target key is unchanged, there is no // need to add a dependency (from the perspective of the target, the update // is a no-op) ForeignKeyValue originalFK; if (ModificationOperator.Update != command.Operator || !ForeignKeyValue.TryCreateTargetKey(fkConstraint, command.OriginalValues, true, out originalFK) || !_keyComparer.Equals(originalFK, fk)) { predecessors.Add(fk, command); } } } } // register all source predecessors if (ModificationOperator.Update == command.Operator || ModificationOperator.Delete == command.Operator) { foreach (ReferentialConstraint fkConstraint in _sourceMap.EnumerateValues(command.Table)) { ForeignKeyValue fk; if (ForeignKeyValue.TryCreateSourceKey(fkConstraint, command.OriginalValues, false, out fk)) { // if this is an update and the source key is unchanged, there is no // need to add a dependency (from the perspective of the source, the update // is a no-op) ForeignKeyValue currentFK; if (ModificationOperator.Update != command.Operator || !ForeignKeyValue.TryCreateSourceKey(fkConstraint, command.CurrentValues, false, out currentFK) || !_keyComparer.Equals(currentFK, fk)) { predecessors.Add(fk, command); } } } } } return predecessors; } /// /// For function commands, we infer constraints based on relationships and entities. For instance, /// we always insert an entity before inserting a relationship referencing that entity. When dynamic /// and function UpdateCommands are mixed, we also fall back on this same interpretation. /// private void AddModelDependencies() { // build up 'required' and 'producing' graphs KeyToListMaprequiredMap = new KeyToListMap (EqualityComparer .Default); KeyToListMap producedMap = new KeyToListMap (EqualityComparer .Default); foreach (UpdateCommand command in this.Vertices) { List required; List produced; command.GetRequiredAndProducedEntities(_translator, out required, out produced); foreach (EntityKey key in required) { requiredMap.Add(key, command); } foreach (EntityKey key in produced) { producedMap.Add(key, command); } } // build up dependencies foreach (var keyAndCommands in requiredMap.KeyValuePairs) { EntityKey key = keyAndCommands.Key; List commandsRequiringKey = keyAndCommands.Value; foreach (UpdateCommand commandProducingKey in producedMap.EnumerateValues(key)) { foreach (UpdateCommand commandRequiringKey in commandsRequiringKey) { // command cannot depend on itself and only function commands // need to worry about model dependencies (dynamic commands know about foreign keys) if (!object.ReferenceEquals(commandProducingKey, commandRequiringKey) && (commandProducingKey.Kind == UpdateCommandKind.Function || commandRequiringKey.Kind == UpdateCommandKind.Function)) { // add a dependency AddEdge(commandProducingKey, commandRequiringKey); } } } } } /// /// Describes an update command's foreign key (source or target) /// private struct ForeignKeyValue { ////// Constructor /// /// Sets Metadata /// Record containing key value /// Indicates whether the source or target end of the constraint /// is being pulled /// Indicates whether this is an insert dependency or a delete /// dependency private ForeignKeyValue(ReferentialConstraint metadata, PropagatorResult record, bool isTarget, bool isInsert) { Metadata = metadata; // construct key IListkeyProperties = isTarget ? metadata.FromProperties : metadata.ToProperties; PropagatorResult[] keyValues = new PropagatorResult[keyProperties.Count]; bool hasNullMember = false; for (int i = 0; i < keyValues.Length; i++) { keyValues[i] = record.GetMemberValue(keyProperties[i]); if (keyValues[i].IsNull) { hasNullMember = true; break; } } if (hasNullMember) { // set key to null to indicate that it is not behaving as a key // (in SQL, keys with null components do not participate in constraints) Key = null; } else { Key = new CompositeKey(keyValues); } IsInsert = isInsert; } /// /// Initialize foreign key object for the target of a foreign key. /// /// Sets Metadata /// Record containing key value /// Indicates whether the key value is being inserted or deleted /// Outputs key object ///true if the record contains key values for this constraint; false otherwise internal static bool TryCreateTargetKey(ReferentialConstraint metadata, PropagatorResult record, bool isInsert, out ForeignKeyValue key) { key = new ForeignKeyValue(metadata, record, true, isInsert); if (null == key.Key) { return false; } return true; } ////// Initialize foreign key object for the source of a foreign key. /// /// Sets Metadata /// Record containing key value /// Indicates whether the key value is being inserted or deleted /// Outputs key object ///true if the record contains key values for this constraint; false otherwise internal static bool TryCreateSourceKey(ReferentialConstraint metadata, PropagatorResult record, bool isInsert, out ForeignKeyValue key) { key = new ForeignKeyValue(metadata, record, false, isInsert); if (null == key.Key) { return false; } return true; } ////// Foreign key metadata. /// internal readonly ReferentialConstraint Metadata; ////// Foreign key value. /// internal readonly CompositeKey Key; ////// Indicates whether this is an inserted or deleted key value. /// internal readonly bool IsInsert; } ////// Equality comparer for ForeignKey class. /// private class ForeignKeyValueComparer : IEqualityComparer{ private readonly IEqualityComparer _baseComparer; internal ForeignKeyValueComparer(IEqualityComparer baseComparer) { _baseComparer = EntityUtil.CheckArgumentNull(baseComparer, "baseComparer"); } public bool Equals(ForeignKeyValue x, ForeignKeyValue y) { return x.IsInsert == y.IsInsert && x.Metadata == y.Metadata && _baseComparer.Equals(x.Key, y.Key); } public int GetHashCode(ForeignKeyValue obj) { return _baseComparer.GetHashCode(obj.Key); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Collections.Generic; using System.Data.Common.Utils; using System.Data.Metadata.Edm; using System.Linq; using System.Diagnostics; namespace System.Data.Mapping.Update.Internal { internal class UpdateCommandOrderer : Graph{ /// /// Gets comparer used to resolve identifiers to actual 'owning' key values (e.g. across referential constraints) /// private readonly ForeignKeyValueComparer _keyComparer; ////// Maps from tables to all "source" referential constraints (where the table declares /// foreign keys) /// private readonly KeyToListMap_sourceMap; /// /// Maps from tables to all "target" referential constraints (where the table is /// referenced by a foreign key) /// private readonly KeyToListMap_targetMap; /// /// Tracks whether any function commands exist in the current payload. /// private readonly bool _hasFunctionCommands; ////// Gets translator producing this graph. /// private readonly UpdateTranslator _translator; internal UpdateCommandOrderer(IEnumerablecommands, UpdateTranslator translator) : base(EqualityComparer .Default) { _translator = translator; _keyComparer = new ForeignKeyValueComparer(_translator.KeyComparer); HashSet tables = new HashSet (); HashSet containers = new HashSet (); // add all vertices (one vertex for every command) foreach (UpdateCommand command in commands) { if (null != command.Table) { tables.Add(command.Table); containers.Add(command.Table.EntityContainer); } AddVertex(command); if (command.Kind == UpdateCommandKind.Function) { _hasFunctionCommands = true; } } // figure out which foreign keys are interesting in this scope InitializeForeignKeyMaps(containers, tables, out _sourceMap, out _targetMap); // add edges for each ordering dependency amongst the commands AddServerGenDependencies(); AddForeignKeyDependencies(); if (_hasFunctionCommands) { AddModelDependencies(); } } private static void InitializeForeignKeyMaps(HashSet containers, HashSet tables, out KeyToListMap sourceMap, out KeyToListMap targetMap) { sourceMap = new KeyToListMap (EqualityComparer .Default); targetMap = new KeyToListMap (EqualityComparer .Default); // Retrieve relationship ends from each container to populate edges in dependency // graph foreach (EntityContainer container in containers) { foreach (EntitySetBase extent in container.BaseEntitySets) { AssociationSet associationSet = extent as AssociationSet; if (null != associationSet) { AssociationSetEnd source = null; AssociationSetEnd target = null; var ends = associationSet.AssociationSetEnds; if (2 == ends.Count) { // source is equivalent to the "to" end of relationship, target is "from" AssociationType associationType = associationSet.ElementType; bool constraintFound = false; ReferentialConstraint fkConstraint = null; foreach (ReferentialConstraint constraint in associationType.ReferentialConstraints) { if (constraintFound) { Debug.Fail("relationship set should have at most one constraint"); } else { constraintFound = true; } source = associationSet.AssociationSetEnds[constraint.ToRole.Name]; target = associationSet.AssociationSetEnds[constraint.FromRole.Name]; fkConstraint = constraint; } Debug.Assert(constraintFound && null != target && null != source, "relationship set must have at least one constraint"); // only understand binary (foreign key) relationships between entity sets if (null != target && null != source) { if (tables.Contains(target.EntitySet)&& tables.Contains(source.EntitySet)) { // Remember metadata sourceMap.Add(source.EntitySet, fkConstraint); targetMap.Add(target.EntitySet, fkConstraint); } } } } } } } // Adds edges to dependency graph for server-generated values. // // Determines which commands produce identifiers (key components) and which commands // consume them. Producers are potentially edge predecessors and consumers are potentially // edge successors. The command objects report the identifiers they produce (OutputIdentifiers) // and the identifiers they consume (InputIdentifiers) private void AddServerGenDependencies() { // Identify all "shared" output parameters (e.g., SQL Server identifiers) Dictionary predecessors = new Dictionary (); foreach (UpdateCommand command in this.Vertices) { foreach (Int64 output in command.OutputIdentifiers) { try { predecessors.Add(output, command); } catch (ArgumentException duplicateKey) { // throw an exception indicating that a key value is generated in two locations // in the store throw EntityUtil.Update(System.Data.Entity.Strings.Update_AmbiguousServerGenIdentifier, duplicateKey, command.GetStateEntries(_translator)); } } } // Identify all dependent input parameters foreach (UpdateCommand command in this.Vertices) { foreach (Int64 input in command.InputIdentifiers) { UpdateCommand from; if (predecessors.TryGetValue(input, out from)) { AddEdge(from, command); } } } } // Adds edges to dependency graph based on foreign keys. private void AddForeignKeyDependencies() { KeyToListMap predecessors = DetermineForeignKeyPredecessors(); AddForeignKeyEdges(predecessors); } // Finds all successors to the given predecessors and registers the resulting dependency edges in this // graph. // // - Commands (updates or inserts) inserting FK "sources" (referencing foreign key) // - Commands (updates or deletes) deleting FK "targets" (referenced by the foreign key) // // To avoid violating constraints, FK references must be created before their referees, and // cannot be deleted before their references. private void AddForeignKeyEdges(KeyToListMap predecessors) { foreach (DynamicUpdateCommand command in this.Vertices.OfType ()) { // register all source successors if (ModificationOperator.Update == command.Operator || ModificationOperator.Insert == command.Operator) { foreach (ReferentialConstraint fkConstraint in _sourceMap.EnumerateValues(command.Table)) { ForeignKeyValue fk; if (ForeignKeyValue.TryCreateSourceKey(fkConstraint, command.CurrentValues, true, out fk)) { // if this is an update and the source key is unchanged, there is no // need to add a dependency (from the perspective of the target, the update // is a no-op) ForeignKeyValue originalFK; if (ModificationOperator.Update != command.Operator || !ForeignKeyValue.TryCreateSourceKey(fkConstraint, command.OriginalValues, true, out originalFK) || !_keyComparer.Equals(originalFK, fk)) { foreach (UpdateCommand predecessor in predecessors.EnumerateValues(fk)) { // don't add self-edges for FK dependencies, since a single operation // in the store is atomic if (predecessor != command) { AddEdge(predecessor, command); } } } } } } // register all target successors if (ModificationOperator.Update == command.Operator || ModificationOperator.Delete == command.Operator) { foreach (ReferentialConstraint fkConstraint in _targetMap.EnumerateValues(command.Table)) { ForeignKeyValue fk; if (ForeignKeyValue.TryCreateTargetKey(fkConstraint, command.OriginalValues, false, out fk)) { // if this is an update and the target key is unchanged, there is no // need to add a dependency (from the perspective of the source, the update // is a no-op) ForeignKeyValue currentFK; if (ModificationOperator.Update != command.Operator || !ForeignKeyValue.TryCreateTargetKey(fkConstraint, command.CurrentValues, false, out currentFK) || !_keyComparer.Equals(currentFK, fk)) { foreach (UpdateCommand predecessor in predecessors.EnumerateValues(fk)) { // don't add self-edges for FK dependencies, since a single operation // in the store is atomic if (predecessor != command) { AddEdge(predecessor, command); } } } } } } } } // Builds a map from foreign key instances to commands, with an entry for every command that may need to // precede some other operation. // // Predecessor commands must precede other commands using those values. There are two kinds of // predecessor: // // - Commands (updates or inserts) inserting FK "targets" (referenced by the foreign key) // - Commands (updates or deletes) deleting FK "sources" (referencing the foreign key) // // To avoid violating constraints, FK values must be created before they are referenced, and // cannot be deleted before their references private KeyToListMap DetermineForeignKeyPredecessors() { KeyToListMap predecessors = new KeyToListMap ( _keyComparer); foreach (DynamicUpdateCommand command in this.Vertices.OfType ()) { if (ModificationOperator.Update == command.Operator || ModificationOperator.Insert == command.Operator) { foreach (ReferentialConstraint fkConstraint in _targetMap.EnumerateValues(command.Table)) { ForeignKeyValue fk; if (ForeignKeyValue.TryCreateTargetKey(fkConstraint, command.CurrentValues, true, out fk)) { // if this is an update and the target key is unchanged, there is no // need to add a dependency (from the perspective of the target, the update // is a no-op) ForeignKeyValue originalFK; if (ModificationOperator.Update != command.Operator || !ForeignKeyValue.TryCreateTargetKey(fkConstraint, command.OriginalValues, true, out originalFK) || !_keyComparer.Equals(originalFK, fk)) { predecessors.Add(fk, command); } } } } // register all source predecessors if (ModificationOperator.Update == command.Operator || ModificationOperator.Delete == command.Operator) { foreach (ReferentialConstraint fkConstraint in _sourceMap.EnumerateValues(command.Table)) { ForeignKeyValue fk; if (ForeignKeyValue.TryCreateSourceKey(fkConstraint, command.OriginalValues, false, out fk)) { // if this is an update and the source key is unchanged, there is no // need to add a dependency (from the perspective of the source, the update // is a no-op) ForeignKeyValue currentFK; if (ModificationOperator.Update != command.Operator || !ForeignKeyValue.TryCreateSourceKey(fkConstraint, command.CurrentValues, false, out currentFK) || !_keyComparer.Equals(currentFK, fk)) { predecessors.Add(fk, command); } } } } } return predecessors; } /// /// For function commands, we infer constraints based on relationships and entities. For instance, /// we always insert an entity before inserting a relationship referencing that entity. When dynamic /// and function UpdateCommands are mixed, we also fall back on this same interpretation. /// private void AddModelDependencies() { // build up 'required' and 'producing' graphs KeyToListMaprequiredMap = new KeyToListMap (EqualityComparer .Default); KeyToListMap producedMap = new KeyToListMap (EqualityComparer .Default); foreach (UpdateCommand command in this.Vertices) { List required; List produced; command.GetRequiredAndProducedEntities(_translator, out required, out produced); foreach (EntityKey key in required) { requiredMap.Add(key, command); } foreach (EntityKey key in produced) { producedMap.Add(key, command); } } // build up dependencies foreach (var keyAndCommands in requiredMap.KeyValuePairs) { EntityKey key = keyAndCommands.Key; List commandsRequiringKey = keyAndCommands.Value; foreach (UpdateCommand commandProducingKey in producedMap.EnumerateValues(key)) { foreach (UpdateCommand commandRequiringKey in commandsRequiringKey) { // command cannot depend on itself and only function commands // need to worry about model dependencies (dynamic commands know about foreign keys) if (!object.ReferenceEquals(commandProducingKey, commandRequiringKey) && (commandProducingKey.Kind == UpdateCommandKind.Function || commandRequiringKey.Kind == UpdateCommandKind.Function)) { // add a dependency AddEdge(commandProducingKey, commandRequiringKey); } } } } } /// /// Describes an update command's foreign key (source or target) /// private struct ForeignKeyValue { ////// Constructor /// /// Sets Metadata /// Record containing key value /// Indicates whether the source or target end of the constraint /// is being pulled /// Indicates whether this is an insert dependency or a delete /// dependency private ForeignKeyValue(ReferentialConstraint metadata, PropagatorResult record, bool isTarget, bool isInsert) { Metadata = metadata; // construct key IListkeyProperties = isTarget ? metadata.FromProperties : metadata.ToProperties; PropagatorResult[] keyValues = new PropagatorResult[keyProperties.Count]; bool hasNullMember = false; for (int i = 0; i < keyValues.Length; i++) { keyValues[i] = record.GetMemberValue(keyProperties[i]); if (keyValues[i].IsNull) { hasNullMember = true; break; } } if (hasNullMember) { // set key to null to indicate that it is not behaving as a key // (in SQL, keys with null components do not participate in constraints) Key = null; } else { Key = new CompositeKey(keyValues); } IsInsert = isInsert; } /// /// Initialize foreign key object for the target of a foreign key. /// /// Sets Metadata /// Record containing key value /// Indicates whether the key value is being inserted or deleted /// Outputs key object ///true if the record contains key values for this constraint; false otherwise internal static bool TryCreateTargetKey(ReferentialConstraint metadata, PropagatorResult record, bool isInsert, out ForeignKeyValue key) { key = new ForeignKeyValue(metadata, record, true, isInsert); if (null == key.Key) { return false; } return true; } ////// Initialize foreign key object for the source of a foreign key. /// /// Sets Metadata /// Record containing key value /// Indicates whether the key value is being inserted or deleted /// Outputs key object ///true if the record contains key values for this constraint; false otherwise internal static bool TryCreateSourceKey(ReferentialConstraint metadata, PropagatorResult record, bool isInsert, out ForeignKeyValue key) { key = new ForeignKeyValue(metadata, record, false, isInsert); if (null == key.Key) { return false; } return true; } ////// Foreign key metadata. /// internal readonly ReferentialConstraint Metadata; ////// Foreign key value. /// internal readonly CompositeKey Key; ////// Indicates whether this is an inserted or deleted key value. /// internal readonly bool IsInsert; } ////// Equality comparer for ForeignKey class. /// private class ForeignKeyValueComparer : IEqualityComparer{ private readonly IEqualityComparer _baseComparer; internal ForeignKeyValueComparer(IEqualityComparer baseComparer) { _baseComparer = EntityUtil.CheckArgumentNull(baseComparer, "baseComparer"); } public bool Equals(ForeignKeyValue x, ForeignKeyValue y) { return x.IsInsert == y.IsInsert && x.Metadata == y.Metadata && _baseComparer.Equals(x.Key, y.Key); } public int GetHashCode(ForeignKeyValue obj) { return _baseComparer.GetHashCode(obj.Key); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DocumentOrderQuery.cs
- CacheRequest.cs
- RayHitTestParameters.cs
- SecurityContextSecurityTokenResolver.cs
- PublisherIdentityPermission.cs
- XmlIlTypeHelper.cs
- AsyncOperation.cs
- InvalidAsynchronousStateException.cs
- XmlArrayItemAttributes.cs
- TypeInitializationException.cs
- ResourcePermissionBase.cs
- Matrix3DConverter.cs
- EventToken.cs
- RMPublishingDialog.cs
- Int32CAMarshaler.cs
- SamlNameIdentifierClaimResource.cs
- _FtpControlStream.cs
- FormViewInsertEventArgs.cs
- CachedFontFamily.cs
- DataExpression.cs
- StringValidatorAttribute.cs
- ConsoleEntryPoint.cs
- EntityCommandExecutionException.cs
- webclient.cs
- HttpNamespaceReservationInstallComponent.cs
- NegotiateStream.cs
- SelectorAutomationPeer.cs
- CubicEase.cs
- GenericsInstances.cs
- PersonalizationEntry.cs
- PropertyPath.cs
- TypeReference.cs
- UnsafeNativeMethods.cs
- GridViewColumnCollectionChangedEventArgs.cs
- ProfessionalColors.cs
- Timer.cs
- DataControlField.cs
- DataGridTextBox.cs
- HtmlInputHidden.cs
- CssClassPropertyAttribute.cs
- DateTimeUtil.cs
- DocumentOrderComparer.cs
- RectAnimationUsingKeyFrames.cs
- XmlQuerySequence.cs
- QueryResponse.cs
- DataTemplateKey.cs
- AdRotatorDesigner.cs
- GeometryConverter.cs
- MimeTypeAttribute.cs
- WebDescriptionAttribute.cs
- Pts.cs
- WhitespaceRuleReader.cs
- InfoCardHelper.cs
- BigIntegerStorage.cs
- GroupStyle.cs
- SqlConnectionStringBuilder.cs
- TreeIterator.cs
- IBuiltInEvidence.cs
- RequiredFieldValidator.cs
- ApplicationCommands.cs
- LocalizableAttribute.cs
- DataGridViewColumnHeaderCell.cs
- Byte.cs
- CurrencyManager.cs
- TreeIterators.cs
- ListViewContainer.cs
- ObjectListCommandEventArgs.cs
- DecimalAnimation.cs
- Bitmap.cs
- SiteMembershipCondition.cs
- DrawingAttributesDefaultValueFactory.cs
- MultiByteCodec.cs
- BitArray.cs
- WindowsListView.cs
- OleDbConnection.cs
- ListViewGroup.cs
- localization.cs
- StringFunctions.cs
- TransformedBitmap.cs
- contentDescriptor.cs
- PeerCollaborationPermission.cs
- InkCanvas.cs
- Graphics.cs
- VersionPair.cs
- TransformValueSerializer.cs
- AttributeCollection.cs
- TabControlAutomationPeer.cs
- OutputCacheSettingsSection.cs
- WorkerRequest.cs
- ClockController.cs
- BehaviorEditorPart.cs
- SafeTimerHandle.cs
- ProfessionalColors.cs
- ProcessThread.cs
- TextParentUndoUnit.cs
- EditorBrowsableAttribute.cs
- DPTypeDescriptorContext.cs
- AuthenticationService.cs
- Triplet.cs
- AssociatedControlConverter.cs