internal override void CreateModelItem(CommandProcessorContext cpc, EditingContext context, EFElement underlyingModelItem) { Debug.Assert(context != null, "null context"); Debug.Assert(Function == null, "Don't call this method if we already have a ModelItem"); Debug.Assert(MappingFunctionEntityType.EntityType != null, "The parent item isn't set up correctly"); Debug.Assert(underlyingModelItem != null, "null underlyingModelItem"); var function = underlyingModelItem as Function; Debug.Assert( function != null, "underlyingModelItem must be of type Function, actual type = " + underlyingModelItem.GetType().FullName); Debug.Assert(!function.EntityModel.IsCSDL, "The function must be in the SSDL"); Context = context; // create a context if we weren't passed one if (cpc == null) { cpc = new CommandProcessorContext( Context, EfiTransactionOriginator.MappingDetailsOriginatorId, Resources.Tx_CreateFunctionMapping); } // create the commands var cmd = new CreateFunctionMappingCommand(MappingFunctionEntityType.EntityType, function, null, _functionType); // set up our post event to fix up the view model cmd.PostInvokeEvent += (o, eventsArgs) => { var mf = cmd.ModificationFunction; Debug.Assert(mf != null, "null ModificationFunction"); // fix up our view model ModelItem = mf; // The parent item for the function mapping view model always has 3 children; insert, update and delete items. If there isn’t // a function mapped for any of these, then there is still a view model item since we want to display the ‘creator node’ text. // Calling this.Parent.AddChild(this) here would make the parent think it had a new child instead of updating the existing one - // so it is correct to _not_ call it here. }; var cmd2 = new DelegateCommand( () => { var mf = ModificationFunction; Debug.Assert( mf != null, "Null ModificationFunction when trying to create view-model dummy nodes in MappingModificationFunctionMapping.CreateModelItem()"); if (mf != null) { //set up _properties and _resultBindings here as they are dummy ViewModel nodes // (i.e. don't correspond to any underlying ModelItem) _properties = new MappingFunctionScalarProperties(context, mf, this); _resultBindings = new MappingResultBindings(context, mf, this); _properties.Parent.AddChild(_properties); _resultBindings.Parent.AddChild(_resultBindings); // now ensure _properties scalar properties children have been calculated // (this creates scalar properties with just the column info // since this ModificationFunction has not yet been mapped) _properties.LoadScalarProperties(); // now try and do some match ups between the function and the entity var mappedEntityType = MappingFunctionEntityType.EntityType as ConceptualEntityType; Debug.Assert( MappingFunctionEntityType.EntityType == null || mappedEntityType != null, "EntityType is not ConceptualEntityType"); if (mappedEntityType != null) { foreach (var mfsp in _properties.ScalarProperties) { // Try to do some auto-matching of the sproc's parameters to the EntityType's properties. // Search for a property in the mapped EntityType's inheritance hierarchy that matches the // parameter's name. First search this EntityType (both its scalar and complex properties), // then search its parents scalar and complex properties and so on up the hierarchy var propNameToSearchFor = mfsp.StoreParameter.LocalName.Value; var propList = new List<Property>(); var entityTypeToSearch = mappedEntityType; // reset this back to the mapped EntityType each time through the loop while (entityTypeToSearch != null && false == ModelHelper.FindScalarPropertyPathByLocalName( entityTypeToSearch, propNameToSearchFor, out propList)) { if (entityTypeToSearch.BaseType == null) { // safety code - this should not happen but will prevent an infinite loop if it does entityTypeToSearch = null; } else { entityTypeToSearch = entityTypeToSearch.BaseType.Target; } } // if propList is still empty that means we did not find a match - so leave the parameter unmapped if (propList.Count > 0) { mfsp.CreateModelItem(cpc, _context, propList); } } } } }); try { // now make the change var cp = new CommandProcessor(cpc); cp.EnqueueCommand(cmd); cp.EnqueueCommand(cmd2); cp.Invoke(); } catch { ModelItem = null; ClearChildren(); throw; } }
// <summary> // NOTE: The association set mapping view model doesn't keep a reference to the mapping model item. Instead, it // keeps it to the AssociationSet and then it can find the AssociationSetMapping as an anti-dep. We don't need to clear // or set the ModelItem property. // </summary> internal override void CreateModelItem(CommandProcessorContext cpc, EditingContext context, EFElement underlyingModelItem) { Debug.Assert(context != null, "The context argument cannot be null"); Debug.Assert(AssociationSet.AssociationSetMapping == null, "Don't call this method if we already have a mapping"); Debug.Assert(underlyingModelItem != null, "The underlyingModelItem cannot be null"); var storeEntityType = underlyingModelItem as EntityType; Debug.Assert( storeEntityType != null, "underlyingModelItem must be of type EntityType, actual type = " + underlyingModelItem.GetType().FullName); Debug.Assert(!storeEntityType.EntityModel.IsCSDL, "The storageEntityType must not be a CSDL EntityType"); Context = context; // create a context if we weren't passed one if (cpc == null) { cpc = new CommandProcessorContext( Context, EfiTransactionOriginator.MappingDetailsOriginatorId, Resources.Tx_CreateAssociationSetMapping); } // create the item var cmd1 = new CreateAssociationSetMappingCommand(MappingAssociation.Association, storeEntityType); // now try and do some match ups by name var cmd2 = new DelegateCommand( () => { Parent.AddChild(this); foreach (var child in Children) { var end = child as MappingAssociationSetEnd; if (end != null) { foreach (var child2 in end.Children) { var mesp = child2 as MappingEndScalarProperty; if (mesp != null) { var tableColumn = MappingAssociationSet.StorageEntityType.GetFirstNamedChildByLocalName(mesp.Property, true) as Property; if (tableColumn != null) { mesp.CreateModelItem(cpc, _context, tableColumn); } } } } } }); // now make the change var cp = new CommandProcessor(cpc); cp.EnqueueCommand(cmd1); cp.EnqueueCommand(cmd2); cp.Invoke(); }