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
- DynamicExpression.cs
- NativeMethods.cs
- Int32Rect.cs
- MailMessage.cs
- DeviceContext2.cs
- ICspAsymmetricAlgorithm.cs
- ConnectionStringSettingsCollection.cs
- ErrorWebPart.cs
- OpenTypeLayoutCache.cs
- AttributeProviderAttribute.cs
- FtpWebRequest.cs
- PropertyEmitterBase.cs
- EdmEntityTypeAttribute.cs
- SharedConnectionInfo.cs
- WhitespaceRuleLookup.cs
- DrawingContext.cs
- GetPageCompletedEventArgs.cs
- DbProviderFactories.cs
- AbstractDataSvcMapFileLoader.cs
- CodeSubDirectory.cs
- SQLInt64.cs
- BamlVersionHeader.cs
- TimeZoneInfo.cs
- streamingZipPartStream.cs
- Int32CollectionConverter.cs
- PageEventArgs.cs
- NavigatingCancelEventArgs.cs
- ApplicationBuildProvider.cs
- NetStream.cs
- ResourcePermissionBase.cs
- ExpressionHelper.cs
- TagPrefixInfo.cs
- DispatcherExceptionEventArgs.cs
- CollectionConverter.cs
- HostedElements.cs
- TextureBrush.cs
- StatusBarItemAutomationPeer.cs
- TripleDES.cs
- WorkflowDebuggerSteppingAttribute.cs
- TextViewBase.cs
- EntityProviderFactory.cs
- StrokeNodeData.cs
- NativeMethodsCLR.cs
- ToggleButtonAutomationPeer.cs
- ListBindingHelper.cs
- OneOfConst.cs
- SetIterators.cs
- CodeGotoStatement.cs
- DatatypeImplementation.cs
- RequestStatusBarUpdateEventArgs.cs
- DefinitionUpdate.cs
- EventMappingSettingsCollection.cs
- Point4DValueSerializer.cs
- BindingManagerDataErrorEventArgs.cs
- XmlWriter.cs
- WindowsImpersonationContext.cs
- Effect.cs
- AddInToken.cs
- StateWorkerRequest.cs
- InstanceData.cs
- AutomationIdentifierGuids.cs
- HttpContext.cs
- StyleBamlTreeBuilder.cs
- DynamicDataManager.cs
- LambdaExpression.cs
- PeerNearMe.cs
- TraceHandler.cs
- ClassicBorderDecorator.cs
- ChannelSinkStacks.cs
- CurrentChangingEventArgs.cs
- TextParagraphCache.cs
- ContentIterators.cs
- CharAnimationBase.cs
- HtmlTernaryTree.cs
- InheritanceRules.cs
- SkinBuilder.cs
- ReadOnlyHierarchicalDataSourceView.cs
- DispatchWrapper.cs
- Tracer.cs
- ContainerActivationHelper.cs
- GPRECTF.cs
- DataGridViewRowErrorTextNeededEventArgs.cs
- BindingGroup.cs
- ObjectDataSourceChooseMethodsPanel.cs
- DocumentSignatureManager.cs
- MemberAssignmentAnalysis.cs
- Operators.cs
- DefaultAuthorizationContext.cs
- CSharpCodeProvider.cs
- Typeface.cs
- TypeHelper.cs
- UnsafeNativeMethods.cs
- PartialTrustVisibleAssemblyCollection.cs
- HtmlControlPersistable.cs
- GlyphManager.cs
- TargetException.cs
- PropertyGrid.cs
- StorageConditionPropertyMapping.cs
- ActivityTrace.cs
- GrowingArray.cs