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); } } }
/// <summary> /// Creates a new MappingFragment in the existing EntityTypeMapping /// based on another MappingFragment (fragToClone) in a different artifact. /// All the other parameters are presumed to already exist in the same artifact /// as the EntityTypeMapping. /// </summary> internal static MappingFragment CloneMappingFragment( CommandProcessorContext cpc, MappingFragment fragToClone, EntityTypeMapping existingEntityTypeMapping, StorageEntitySet existingEntitySet) { var createFragmentCommand = new CreateMappingFragmentCommand(existingEntityTypeMapping, existingEntitySet); var cp = new CommandProcessor(cpc, createFragmentCommand); cp.Invoke(); var frag = createFragmentCommand.MappingFragment; Debug.Assert(frag != null, "Could not locate or create the required mapping fragment"); if (frag != null) { foreach (var sp in fragToClone.ScalarProperties()) { Property entityProperty = null; if (sp.Name != null && sp.Name.Target != null && sp.Name.Target.LocalName != null && sp.Name.Target.LocalName.Value != null) { entityProperty = ModelHelper.FindPropertyForEntityTypeMapping( existingEntityTypeMapping, sp.Name.Target.LocalName.Value); Debug.Assert( entityProperty != null, "Cannot find Property with name " + sp.Name.Target.LocalName.Value + " for EntityTypeMapping " + existingEntityTypeMapping.ToPrettyString()); } Property tableColumn = null; if (frag.StoreEntitySet != null && frag.StoreEntitySet.Target != null && frag.StoreEntitySet.Target.EntityType != null && frag.StoreEntitySet.Target.EntityType.Target != null && sp.ColumnName != null && sp.ColumnName.Target != null && sp.ColumnName.Target.LocalName != null && sp.ColumnName.Target.LocalName.Value != null) { tableColumn = ModelHelper.FindProperty( frag.StoreEntitySet.Target.EntityType.Target, sp.ColumnName.Target.LocalName.Value); Debug.Assert( tableColumn != null, "Cannot find Property with name " + sp.ColumnName.Target.LocalName.Value + " for EntityType " + frag.StoreEntitySet.Target.EntityType.Target.ToPrettyString()); } if (entityProperty != null && tableColumn != null) { var createScalarCommand = new CreateFragmentScalarPropertyCommand(frag, entityProperty, tableColumn); var cp2 = new CommandProcessor(cpc, createScalarCommand); cp2.Invoke(); } } } return(frag); }