Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Map / Update / Internal / FunctionMappingTranslator.cs / 1305376 / FunctionMappingTranslator.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.Linq; using System.Data.Entity; namespace System.Data.Mapping.Update.Internal { ////// Function mapping translators are defined per extent (entity set /// or association set) and manage the creation of function commands. /// internal abstract class FunctionMappingTranslator { ////// Requires: this translator must be registered to handle the entity set /// for the given state entry. /// /// Translates the given state entry to a command. /// /// Parent update translator (global state for the workload) /// State entry to translate. Must belong to the /// entity/association set handled by this translator ///Command corresponding to the given state entry internal abstract FunctionUpdateCommand Translate( UpdateTranslator translator, ExtractedStateEntry stateEntry); ////// Initialize a translator for the given entity set mapping. /// /// Entity set mapping. ///Translator. internal static FunctionMappingTranslator CreateEntitySetFunctionMappingTranslator( StorageEntitySetMapping setMapping) { return new EntitySetFunctionMappingTranslator(setMapping); } ////// Initialize a translator for the given association set mapping. /// /// Association set mapping. ///Translator. internal static FunctionMappingTranslator CreateAssociationSetFunctionMappingTranslator( StorageAssociationSetMapping setMapping) { return new AssociationSetFunctionMappingTranslator(setMapping); } private sealed class EntitySetFunctionMappingTranslator : FunctionMappingTranslator { private readonly Dictionarym_typeMappings; internal EntitySetFunctionMappingTranslator(StorageEntitySetMapping setMapping) { Debug.Assert(null != setMapping && null != setMapping.FunctionMappings && 0 < setMapping.FunctionMappings.Count, "set mapping must exist and must specify function mappings"); m_typeMappings = new Dictionary (); foreach (StorageEntityTypeFunctionMapping typeMapping in setMapping.FunctionMappings) { m_typeMappings.Add(typeMapping.EntityType, typeMapping); } } internal override FunctionUpdateCommand Translate( UpdateTranslator translator, ExtractedStateEntry stateEntry) { var mapping = GetFunctionMapping(stateEntry); StorageEntityTypeFunctionMapping typeMapping = mapping.Item1; StorageFunctionMapping functionMapping = mapping.Item2; EntityKey entityKey = stateEntry.Source.EntityKey; var stateEntries = new HashSet { stateEntry.Source }; // gather all referenced association ends var collocatedEntries = // find all related entries corresponding to collocated association types from end in functionMapping.CollocatedAssociationSetEnds join candidateEntry in translator.GetRelationships(entityKey) on end.CorrespondingAssociationEndMember.DeclaringType equals candidateEntry.EntitySet.ElementType select Tuple.Create(end.CorrespondingAssociationEndMember, candidateEntry); var currentReferenceEnds = new Dictionary (); var originalReferenceEnds = new Dictionary (); foreach (var candidate in collocatedEntries) { ProcessReferenceCandidate(entityKey, stateEntries, currentReferenceEnds, originalReferenceEnds, candidate.Item1, candidate.Item2); } // create function object FunctionUpdateCommand command = new FunctionUpdateCommand(functionMapping, translator, stateEntries.ToList().AsReadOnly(), stateEntry); // bind all function parameters BindFunctionParameters(translator, stateEntry, functionMapping, command, currentReferenceEnds, originalReferenceEnds); // interpret all result bindings if (null != functionMapping.ResultBindings) { foreach (StorageFunctionResultBinding resultBinding in functionMapping.ResultBindings) { PropagatorResult result = stateEntry.Current.GetMemberValue(resultBinding.Property); command.AddResultColumn(translator, resultBinding.ColumnName, result); } } return command; } private static void ProcessReferenceCandidate( EntityKey source, HashSet stateEntries, Dictionary currentReferenceEnd, Dictionary originalReferenceEnd, AssociationEndMember endMember, IEntityStateEntry candidateEntry) { Func getEntityKey = (record, ordinal) => (EntityKey)record[ordinal]; Action > findMatch = (record, registerTarget) => { // find the end corresponding to the 'to' end int toOrdinal = record.GetOrdinal(endMember.Name); Debug.Assert(-1 != toOrdinal, "to end of relationship doesn't exist in record"); // the 'from' end must be the other end int fromOrdinal = 0 == toOrdinal ? 1 : 0; if (getEntityKey(record, fromOrdinal) == source) { stateEntries.Add(candidateEntry); registerTarget(candidateEntry); } }; switch (candidateEntry.State) { case EntityState.Unchanged: findMatch( candidateEntry.CurrentValues, (target) => { currentReferenceEnd.Add(endMember, target); originalReferenceEnd.Add(endMember, target); }); break; case EntityState.Added: findMatch( candidateEntry.CurrentValues, (target) => currentReferenceEnd.Add(endMember, target)); break; case EntityState.Deleted: findMatch( candidateEntry.OriginalValues, (target) => originalReferenceEnd.Add(endMember, target)); break; default: break; } } private Tuple GetFunctionMapping(ExtractedStateEntry stateEntry) { // choose mapping based on type and operation StorageFunctionMapping functionMapping; EntityType entityType; if (null != stateEntry.Current) { entityType = (EntityType)stateEntry.Current.StructuralType; } else { entityType = (EntityType)stateEntry.Original.StructuralType; } StorageEntityTypeFunctionMapping typeMapping = m_typeMappings[entityType]; switch (stateEntry.State) { case EntityState.Added: functionMapping = typeMapping.InsertFunctionMapping; EntityUtil.ValidateNecessaryFunctionMapping(functionMapping, "Insert", stateEntry.Source, "EntityType", entityType.Name); break; case EntityState.Deleted: functionMapping = typeMapping.DeleteFunctionMapping; EntityUtil.ValidateNecessaryFunctionMapping(functionMapping, "Delete", stateEntry.Source, "EntityType", entityType.Name); break; case EntityState.Unchanged: case EntityState.Modified: functionMapping = typeMapping.UpdateFunctionMapping; EntityUtil.ValidateNecessaryFunctionMapping(functionMapping, "Update", stateEntry.Source, "EntityType", entityType.Name); break; default: functionMapping = null; Debug.Fail("unexpected state"); break; } return Tuple.Create(typeMapping, functionMapping); } // Walks through all parameter bindings in the function mapping and binds the parameters to the // requested properties of the given state entry. private void BindFunctionParameters(UpdateTranslator translator, ExtractedStateEntry stateEntry, StorageFunctionMapping functionMapping, FunctionUpdateCommand command, Dictionary currentReferenceEnds, Dictionary originalReferenceEnds) { // bind all parameters foreach (StorageFunctionParameterBinding parameterBinding in functionMapping.ParameterBindings) { PropagatorResult result; // extract value if (null != parameterBinding.MemberPath.AssociationSetEnd) { // find the relationship entry corresponding to the navigation AssociationEndMember endMember = parameterBinding.MemberPath.AssociationSetEnd.CorrespondingAssociationEndMember; IEntityStateEntry relationshipEntry; bool hasTarget = parameterBinding.IsCurrent ? currentReferenceEnds.TryGetValue(endMember, out relationshipEntry) : originalReferenceEnds.TryGetValue(endMember, out relationshipEntry); if (!hasTarget) { if (endMember.RelationshipMultiplicity == RelationshipMultiplicity.One) { string entitySetName = stateEntry.Source.EntitySet.Name; string associationSetName = parameterBinding.MemberPath.AssociationSetEnd.ParentAssociationSet.Name; throw EntityUtil.Update(Strings.Update_MissingRequiredRelationshipValue(entitySetName, associationSetName), null, command.GetStateEntries(translator)); } else { result = PropagatorResult.CreateSimpleValue(PropagatorFlags.NoFlags, null); } } else { // get the actual value PropagatorResult relationshipResult = parameterBinding.IsCurrent ? translator.RecordConverter.ConvertCurrentValuesToPropagatorResult(relationshipEntry, ModifiedPropertiesBehavior.AllModified) : translator.RecordConverter.ConvertOriginalValuesToPropagatorResult(relationshipEntry, ModifiedPropertiesBehavior.AllModified); PropagatorResult endResult = relationshipResult.GetMemberValue(endMember); EdmProperty keyProperty = (EdmProperty)parameterBinding.MemberPath.Members[0]; result = endResult.GetMemberValue(keyProperty); } } else { // walk through the member path to find the appropriate propagator results result = parameterBinding.IsCurrent ? stateEntry.Current : stateEntry.Original; for (int i = parameterBinding.MemberPath.Members.Count; i > 0;) { --i; EdmMember member = parameterBinding.MemberPath.Members[i]; result = result.GetMemberValue(member); } } // create DbParameter command.SetParameterValue(result, parameterBinding, translator); } // Add rows affected parameter command.RegisterRowsAffectedParameter(functionMapping.RowsAffectedParameter); } } private sealed class AssociationSetFunctionMappingTranslator : FunctionMappingTranslator { // If this value is null, it indicates that the association set is // only implicitly mapped as part of an entity set private readonly StorageAssociationSetFunctionMapping m_mapping; internal AssociationSetFunctionMappingTranslator(StorageAssociationSetMapping setMapping) { if (null != setMapping) { m_mapping = setMapping.FunctionMapping; } } internal override FunctionUpdateCommand Translate( UpdateTranslator translator, ExtractedStateEntry stateEntry) { if (null == m_mapping) { return null; } bool isInsert = EntityState.Added == stateEntry.State; EntityUtil.ValidateNecessaryFunctionMapping( isInsert ? m_mapping.InsertFunctionMapping : m_mapping.DeleteFunctionMapping, isInsert ? "Insert" : "Delete", stateEntry.Source, "AssociationSet", m_mapping.AssociationSet.Name); // initialize a new command StorageFunctionMapping functionMapping = isInsert ? m_mapping.InsertFunctionMapping : m_mapping.DeleteFunctionMapping; FunctionUpdateCommand command = new FunctionUpdateCommand(functionMapping, translator, new [] { stateEntry.Source }.ToList().AsReadOnly(), stateEntry); // extract the relationship values from the state entry PropagatorResult recordResult; if (isInsert) { recordResult = stateEntry.Current; } else { recordResult = stateEntry.Original; } // bind parameters foreach (StorageFunctionParameterBinding parameterBinding in functionMapping.ParameterBindings) { // extract the relationship information Debug.Assert(2 == parameterBinding.MemberPath.Members.Count, "relationship parameter binding member " + "path should include the relationship end and key property only"); EdmProperty keyProperty = (EdmProperty)parameterBinding.MemberPath.Members[0]; AssociationEndMember endMember = (AssociationEndMember)parameterBinding.MemberPath.Members[1]; // get the end member PropagatorResult endResult = recordResult.GetMemberValue(endMember); PropagatorResult keyResult = endResult.GetMemberValue(keyProperty); command.SetParameterValue(keyResult, parameterBinding, translator); } // add rows affected output parameter command.RegisterRowsAffectedParameter(functionMapping.RowsAffectedParameter); return command; } } } } // 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
- PagedDataSource.cs
- ShaderEffect.cs
- XmlTextReaderImplHelpers.cs
- EventArgs.cs
- SerializationAttributes.cs
- AdapterUtil.cs
- SlotInfo.cs
- RequestBringIntoViewEventArgs.cs
- EncryptedReference.cs
- RowSpanVector.cs
- XhtmlBasicCalendarAdapter.cs
- CopyNodeSetAction.cs
- ListBase.cs
- _FtpControlStream.cs
- SmiEventStream.cs
- OpCodes.cs
- DataGridViewColumnCollection.cs
- CompilerWrapper.cs
- FreezableCollection.cs
- CaseExpr.cs
- HttpRequestCacheValidator.cs
- CrossSiteScriptingValidation.cs
- ButtonField.cs
- TableRowCollection.cs
- HttpCachePolicy.cs
- PresentationAppDomainManager.cs
- Qualifier.cs
- CoTaskMemHandle.cs
- StaticContext.cs
- ControlCollection.cs
- BamlLocalizabilityResolver.cs
- ListViewInsertedEventArgs.cs
- NavigationProperty.cs
- PathParser.cs
- ExpandCollapsePattern.cs
- ExtractorMetadata.cs
- RuntimeWrappedException.cs
- IIS7UserPrincipal.cs
- SystemNetworkInterface.cs
- WindowsPrincipal.cs
- FormsAuthenticationCredentials.cs
- DataObjectAttribute.cs
- PropertyGridView.cs
- SafeRegistryHandle.cs
- FlowDocumentPageViewerAutomationPeer.cs
- ManagementObject.cs
- AnimationStorage.cs
- XmlSchemaSubstitutionGroup.cs
- CheckPair.cs
- Camera.cs
- TypeConverterHelper.cs
- WinFormsSecurity.cs
- ToolStripStatusLabel.cs
- TransactionsSectionGroup.cs
- ComponentEditorPage.cs
- LinqDataSourceStatusEventArgs.cs
- AnimatedTypeHelpers.cs
- XmlTextAttribute.cs
- GraphicsContext.cs
- Application.cs
- RectConverter.cs
- PerformanceCountersElement.cs
- DataBoundControlHelper.cs
- PropertyMapper.cs
- TextShapeableCharacters.cs
- CatchDesigner.xaml.cs
- EntityDataSourceWrapperPropertyDescriptor.cs
- OperationCanceledException.cs
- CompositeControl.cs
- ControlIdConverter.cs
- ObjectDataProvider.cs
- UnaryNode.cs
- RTTypeWrapper.cs
- SqlTransaction.cs
- AutomationElement.cs
- OutputWindow.cs
- SerialPinChanges.cs
- ParamArrayAttribute.cs
- ConfigurationPermission.cs
- TextTreeText.cs
- ConfigurationPropertyCollection.cs
- FieldMetadata.cs
- FamilyTypeface.cs
- String.cs
- EntityDataSourceDataSelectionPanel.designer.cs
- InputBuffer.cs
- PersonalizationStateQuery.cs
- TraceUtils.cs
- AuthenticateEventArgs.cs
- FixedSOMPageElement.cs
- QilFactory.cs
- invalidudtexception.cs
- StructuredType.cs
- ResumeStoryboard.cs
- SystemIPv4InterfaceProperties.cs
- ServiceThrottlingBehavior.cs
- ComAwareEventInfo.cs
- AppliedDeviceFiltersEditor.cs
- SQLStringStorage.cs
- PersonalizationStateInfoCollection.cs