private void PreserveScalarPropertyMapping(
            CommandProcessorContext cpc, ScalarProperty scalarPropertyMapping, Property createdComplexTypeProperty)
        {
            // this represents a path to a scalar Property in the original EntityType properties tree
            var propertiesChain = scalarPropertyMapping.GetMappedPropertiesList();

            // we need to create a corresponding path in changed EntityType
            // in order to do that we need to replace first (root) item with a created property from ComplexType...
            propertiesChain.RemoveAt(0);
            propertiesChain.Insert(0, createdComplexTypeProperty);
            // and add the created EntityType complex property as a root of that path
            propertiesChain.Insert(0, _createdComplexProperty);
            var cmd = new CreateFragmentScalarPropertyTreeCommand(_entityType, propertiesChain, scalarPropertyMapping.ColumnName.Target);

            CommandProcessor.InvokeSingleCommand(cpc, cmd);
        }
        // <summary>
        //     The mapping view model contains a MappingScalarProperty for every column in the table.  The user can clear out the
        //     underlying scalar property, but that doesn't remove or add the MappingScalarProperty.  We need the placeholder
        //     in the view model to show the nodes in the Trid even if there isn't a mapping.  Thus, we don't need to call
        //     this.Parent.AddChild(this) since its already there.
        // </summary>
        internal void CreateModelItem(CommandProcessorContext cpc, EditingContext context, List<Property> propertiesChain)
        {
            Debug.Assert(propertiesChain != null, "The propertiesChain cannot be null");
            Debug.Assert(context != null, "The context argument cannot be null");
            Debug.Assert(ScalarProperty == null, "Don't call this method if we already have a ModelItem");
            Debug.Assert(MappingStorageEntityType.StorageEntityType != null, "The parent item isn't set up correctly");

            Debug.Assert(propertiesChain.Count > 0, "propertiesChain cannot be empty");

            Context = context;

            // local shortcuts
            EntityType entityType = MappingConceptualEntityType.ConceptualEntityType;
            EntityType table = MappingStorageEntityType.StorageEntityType;

            // find the s-side property based on the value stored in this.ColumnName
            var tableColumn = table.GetFirstNamedChildByLocalName(ColumnName) as Property;
            Debug.Assert(tableColumn != null, "Failed looking up table column for ScalarProperty.");
            if (tableColumn == null)
            {
                return;
            }

            try
            {
                // now make the change
                if (cpc == null)
                {
                    cpc = new CommandProcessorContext(
                        Context, EfiTransactionOriginator.MappingDetailsOriginatorId, Resources.Tx_CreateScalarProperty);
                }
                var cmd = new CreateFragmentScalarPropertyTreeCommand(entityType, propertiesChain, tableColumn);
                cmd.PostInvokeEvent += (o, eventsArgs) =>
                    {
                        var sp = cmd.ScalarProperty;
                        Debug.Assert(sp != null, "CreateFragmentScalarPropertyTreeCommand failed to create ScalarProperty");

                        // fix up our view model (we don't have to add this to the parent's children collection
                        // because we created a placeholder row already for every column in the table)
                        ModelItem = sp;
                    };

                var cp = new CommandProcessor(cpc, cmd);
                cp.Invoke();
            }
            catch
            {
                ModelItem = null;

                throw;
            }
        }
        internal void ChangeScalarProperty(EditingContext context, List<Property> newPropertiesChain)
        {
            if (ModelItem != null)
            {
                var propertiesChain = ScalarProperty.GetMappedPropertiesList();
                var changeNeeded = false;
                // is it different than what we have already?
                if (propertiesChain.Count != newPropertiesChain.Count)
                {
                    changeNeeded = true;
                }
                else
                {
                    for (var i = 0; i < propertiesChain.Count; i++)
                    {
                        if (propertiesChain[i] != newPropertiesChain[i])
                        {
                            changeNeeded = true;
                            break;
                        }
                    }
                }

                if (changeNeeded)
                {
                    Debug.Assert(ScalarProperty.ColumnName.Status == BindingStatus.Known, "Table column not found");
                    if (ScalarProperty.ColumnName.Status == BindingStatus.Known)
                    {
                        // delete old and create new ScalarProperty in one transaction
                        var cpc = new CommandProcessorContext(
                            context, EfiTransactionOriginator.MappingDetailsOriginatorId, Resources.Tx_ChangeScalarProperty);
                        var cmd1 = ScalarProperty.GetDeleteCommand();
                        var cmd2 = new CreateFragmentScalarPropertyTreeCommand(
                            MappingConceptualEntityType.ConceptualEntityType, newPropertiesChain, ScalarProperty.ColumnName.Target);
                        cmd2.PostInvokeEvent += (o, eventsArgs) =>
                            {
                                var sp = cmd2.ScalarProperty;
                                Debug.Assert(sp != null, "CreateFragmentScalarPropertyTreeCommand falied to create a ScalarProperty");
                                ModelItem = sp;
                            };

                        var cp = new CommandProcessor(cpc, cmd1, cmd2);
                        try
                        {
                            cp.Invoke();
                        }
                        catch
                        {
                            ModelItem = null;

                            throw;
                        }
                    }
                }
            }
            else
            {
                // if we don't have a scalar property, there is nothing to set this into;
                // create the scalar property first
                throw new InvalidOperationException();
            }
        }
        private void ProcessMappingFragment(EntityInfo info, EntityType table, MappingFragment frag)
        {
            // move any scalar mappings to this fragment if they aren't there
            foreach (var sp in info.NonKeyScalars)
            {
                Debug.Assert(sp.ColumnName.Target != null, "Found a ScalarProperty with an unknown column binding");

                if (sp.ColumnName.Target.Parent == table
                    && sp.MappingFragment != frag)
                {
                    // delete the old, create the new
                    AddToDeleteList(sp);

                    var cmd = new CreateFragmentScalarPropertyTreeCommand(frag, sp.GetMappedPropertiesList(), sp.ColumnName.Target);
                    var cp = new CommandProcessor(_cpc, cmd);
                    cp.Invoke();
                }
            }

            // move any conditions to this fragment if they aren't there
            foreach (var cond in info.Conditions)
            {
                Debug.Assert(cond.ColumnName.Target != null, "Found a Condition with an unknown column binding");

                if (cond.ColumnName.Target.Parent == table
                    && cond.MappingFragment != frag)
                {
                    // save off the condition information
                    bool? isNull = null;
                    if (cond.IsNull.Value == Condition.IsNullConstant)
                    {
                        isNull = true;
                    }
                    else if (cond.IsNull.Value == Condition.IsNotNullConstant)
                    {
                        isNull = false;
                    }

                    var conditionValue = cond.Value.Value;
                    var column = cond.ColumnName.Target;

                    // delete the old, create the new
                    AddToDeleteList(cond);

                    var cmd = new CreateFragmentConditionCommand(frag, column, isNull, conditionValue);
                    var cp = new CommandProcessor(_cpc, cmd);
                    cp.Invoke();
                }
            }

            // build a list of all of the keys
            var keysToMap = new List<Property>();
            keysToMap.AddRange(info.KeyProperties);

            // move any key scalar mappings to this fragment if they exist in a different one - provided they are for the same table
            foreach (var sp in info.KeyScalars)
            {
                Debug.Assert(sp.ColumnName.Target != null, "Found a ScalarProperty with an unknown column binding");

                if (sp.ColumnName.Target.Parent == table
                    && sp.MappingFragment != frag)
                {
                    var property = sp.Name.Target;
                    var column = sp.ColumnName.Target;

                    // delete the old, create the new
                    AddToDeleteList(sp);

                    var cmd = new CreateFragmentScalarPropertyCommand(frag, property, column);
                    var cp = new CommandProcessor(_cpc, cmd);
                    cp.Invoke();
                }

                // since we've mapped this one now, remove it from our list of things to do
                keysToMap.Remove(sp.Name.Target);
            }

            // if its TPH, all keys need to be here
            // (Note: if it's not TPH the user needs to specify any missing keys manually)
            if (info.InheritanceStrategy == InheritanceMappingStrategy.TablePerHierarchy)
            {
                // loop through the base most type's keys and add those that we haven't mapped
                foreach (var keyRemaining in keysToMap)
                {
                    var sp = FindKeyMappingInAllParents(info, keyRemaining);
                    if (sp != null
                        && sp.ColumnName.Target != null
                        && sp.ColumnName.Target.Parent == table)
                    {
                        var cmd = new CreateFragmentScalarPropertyCommand(frag, sp.Name.Target, sp.ColumnName.Target);
                        var cp = new CommandProcessor(_cpc, cmd);
                        cp.Invoke();
                    }
                }
            }

            // replicate all non-key base type scalars here if the parent uses a Default ETM
            // (since there is no parent IsTypeOf ETM from which to "inherit" them)
            if (info.Parent != null
                && info.Parent.UsesEntityTypeMappingKind(EntityTypeMappingKind.Default))
            {
                // first gather the list of scalars from all parents
                var parentScalars = new List<ScalarProperty>();
                GatherNonKeyScalarsFromAllParents(info.Parent, parentScalars);

                // then build a list of those scalars used in our fragment
                var existingMappedProperties = new HashSet<Property>();
                foreach (var existingScalar in frag.ScalarProperties())
                {
                    existingMappedProperties.Add(existingScalar.Name.Target);
                }

                // finally, add those in that aren't already in the fragment
                foreach (var sp in parentScalars)
                {
                    Debug.Assert(sp.ColumnName.Target != null, "Found a ScalarProperty with an unknown column binding");

                    // don't duplicate and only add those that use the same table as us
                    if (existingMappedProperties.Contains(sp.Name.Target) == false
                        && sp.ColumnName.Target.EntityType == table)
                    {
                        var cmd = new CreateFragmentScalarPropertyTreeCommand(frag, sp.GetMappedPropertiesList(), sp.ColumnName.Target);
                        var cp = new CommandProcessor(_cpc, cmd);
                        cp.Invoke();

                        existingMappedProperties.Add(sp.Name.Target);
                    }
                }
            }

            // make sure that we don't have any extra scalars
            // so gather the list of all SPs we expect to be here
            var expectedMappedProperties = new List<Property>();
            expectedMappedProperties.AddRange(info.KeyProperties);
            expectedMappedProperties.AddRange(info.NonKeyProperties);
            if (info.Parent != null
                && info.Parent.UsesEntityTypeMappingKind(EntityTypeMappingKind.Default))
            {
                GatherNonKeyPropertiesFromAllParents(info.Parent, expectedMappedProperties);
            }

            // remove any that aren't in our expected list
            foreach (var sp in frag.ScalarProperties())
            {
                if (expectedMappedProperties.Contains(sp.Name.Target) == false)
                {
                    AddToDeleteList(sp);
                }
            }
        }
 private void PreserveScalarPropertyMapping(
     CommandProcessorContext cpc, ScalarProperty scalarPropertyMapping, Property createdComplexTypeProperty)
 {
     // this represents a path to a scalar Property in the original EntityType properties tree
     var propertiesChain = scalarPropertyMapping.GetMappedPropertiesList();
     // we need to create a corresponding path in changed EntityType
     // in order to do that we need to replace first (root) item with a created property from ComplexType...
     propertiesChain.RemoveAt(0);
     propertiesChain.Insert(0, createdComplexTypeProperty);
     // and add the created EntityType complex property as a root of that path
     propertiesChain.Insert(0, _createdComplexProperty);
     var cmd = new CreateFragmentScalarPropertyTreeCommand(_entityType, propertiesChain, scalarPropertyMapping.ColumnName.Target);
     CommandProcessor.InvokeSingleCommand(cpc, cmd);
 }