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
- ListViewPagedDataSource.cs
- FileReader.cs
- WizardPanel.cs
- TextChangedEventArgs.cs
- CubicEase.cs
- SplitterEvent.cs
- NullableFloatAverageAggregationOperator.cs
- configsystem.cs
- NestedContainer.cs
- Filter.cs
- SqlDataSourceTableQuery.cs
- ComEventsInfo.cs
- StylusPointProperty.cs
- MessageQueueCriteria.cs
- EntityClientCacheKey.cs
- StringStorage.cs
- XmlLanguageConverter.cs
- FieldBuilder.cs
- FixedSOMFixedBlock.cs
- SqlCacheDependencyDatabaseCollection.cs
- CultureTable.cs
- DataGridViewRowsAddedEventArgs.cs
- ConvertEvent.cs
- ResourcePool.cs
- MailBnfHelper.cs
- FunctionMappingTranslator.cs
- Latin1Encoding.cs
- LogRestartAreaEnumerator.cs
- DateTimeParse.cs
- DoubleStorage.cs
- FilterFactory.cs
- TreeNodeSelectionProcessor.cs
- FormViewInsertEventArgs.cs
- XmlDownloadManager.cs
- StateWorkerRequest.cs
- ActivityStateQuery.cs
- NullRuntimeConfig.cs
- ExtendedProtectionPolicyElement.cs
- FontDriver.cs
- SspiNegotiationTokenProvider.cs
- DesignerView.xaml.cs
- DesignTimeSiteMapProvider.cs
- XmlStreamStore.cs
- NameTable.cs
- BamlResourceSerializer.cs
- CompensationDesigner.cs
- OleDbRowUpdatingEvent.cs
- SecurityTokenProvider.cs
- DataObject.cs
- MemoryFailPoint.cs
- DeleteHelper.cs
- PersonalizationEntry.cs
- LockRecoveryTask.cs
- BaseProcessor.cs
- VariableQuery.cs
- TdsParserStateObject.cs
- FirstMatchCodeGroup.cs
- SqlFactory.cs
- XmlUrlResolver.cs
- CollectionExtensions.cs
- BitmapPalettes.cs
- TypeHelper.cs
- AttachedPropertyMethodSelector.cs
- MenuItemCollection.cs
- hresults.cs
- SecurityState.cs
- ValidatingReaderNodeData.cs
- CompressEmulationStream.cs
- HelpProvider.cs
- PrintDialogDesigner.cs
- coordinator.cs
- DataRecordInfo.cs
- IriParsingElement.cs
- SplashScreen.cs
- HttpListenerRequestUriBuilder.cs
- SqlNotificationRequest.cs
- VerificationException.cs
- ContextBase.cs
- EdmScalarPropertyAttribute.cs
- EntitySqlQueryBuilder.cs
- XmlSerializationReader.cs
- Stacktrace.cs
- PreProcessor.cs
- NavigationWindow.cs
- SelectionEditingBehavior.cs
- XmlCustomFormatter.cs
- HttpBufferlessInputStream.cs
- webeventbuffer.cs
- ObjectTag.cs
- SpanIndex.cs
- TaskFormBase.cs
- DataViewManagerListItemTypeDescriptor.cs
- ComponentResourceKey.cs
- ConstructorBuilder.cs
- XpsS0ValidatingLoader.cs
- DeclarativeCatalogPart.cs
- PagePropertiesChangingEventArgs.cs
- Separator.cs
- MsmqDecodeHelper.cs
- FastEncoderWindow.cs