private void RegisterRenameTableHint(StoredTypeInfo oldType, StoredTypeInfo newType) { if (EnsureTableExist(oldType)) { schemaHints.Add(new RenameHint(GetTablePath(oldType), GetTablePath(newType))); } }
private void RegisterRenameFieldHint( StoredTypeInfo oldType, StoredTypeInfo newType, string oldColumnName, string newColumnName) { if (EnsureTableExist(oldType) && EnsureFieldExist(oldType, oldColumnName)) { schemaHints.Add( new RenameHint(GetColumnPath(oldType, oldColumnName), GetColumnPath(newType, newColumnName))); } }
private void GenerateClearReferenceHint( StoredTypeInfo removedType, StoredTypeInfo updatedType, StoredAssociationInfo association, bool inverse) { if (association.ReferencingField.IsEntitySet && association.ConnectorType == null) { // There is nothing to cleanup in class containing EntitySet<T> property, // when T is removed, and EntitySet<T> was paired to a property of T. return; } var identityFieldsOfRemovedType = removedType.AllFields.Where(f => f.IsPrimaryKey).ToList(); var identityFieldsOfUpdatedType = association.ConnectorType != null ? association.ConnectorType.Fields .Single(field => field.Name == ((association.IsMaster ^ inverse) ? WellKnown.SlaveFieldName : WellKnown.MasterFieldName)) .Fields : association.ReferencingField.Fields; var pairedIdentityFields = JoinFieldsByOriginalName(identityFieldsOfRemovedType, identityFieldsOfUpdatedType); var pairedIdentityColumns = AssociateMappedFields(pairedIdentityFields); if (pairedIdentityColumns == null) { throw new InvalidOperationException( String.Format(Strings.ExPairedIdentityColumnsForTypesXAndXNotFound, removedType, updatedType)); } var sourceTablePath = GetTablePath(updatedType); var identities = pairedIdentityColumns.Select(pair => new IdentityPair( GetColumnPath(updatedType, pair.Second), GetColumnPath(removedType, pair.First), false)) .ToList(); if (removedType.Hierarchy.InheritanceSchema != InheritanceSchema.ConcreteTable) { identities.Add(new IdentityPair( GetColumnPath(removedType, GetTypeIdMappingName(removedType)), removedType.TypeId.ToString(), true)); } var updatedColumns = pairedIdentityColumns.Select(pair => new Pair <string, object>(GetColumnPath(updatedType, pair.Second), null)) .ToList(); if (association.ConnectorType == null) { schemaHints.Add(new UpdateDataHint(sourceTablePath, identities, updatedColumns)); } else { schemaHints.Add(new DeleteDataHint(sourceTablePath, identities)); } }
private string GetColumnPath(StoredTypeInfo type, string columnName) { var nodeName = GetTableName(type); // Due to current implementation of domain model FieldInfo.MappingName is not correct, // it has naming rules unapplied, corresponding ColumnInfo.Name however is correct. // StoredFieldInfo.MappingName is taken directly from FieldInfo.MappingName and thus is incorrect too. // We need to apply naming rules here to make it work. var actualColumnName = nameBuilder.ApplyNamingRules(columnName); return(string.Format("Tables/{0}/Columns/{1}", nodeName, actualColumnName)); }
private void GenerateClearReferenceHints( StoredTypeInfo removedType, StoredTypeInfo[] updatedTypes, StoredAssociationInfo association, bool inverse) { foreach (var updatedType in updatedTypes) { GenerateClearReferenceHint(removedType, updatedType, association, inverse); } }
private void MapType(StoredTypeInfo oldType, StoredTypeInfo newType) { if (typeMapping.TryGetValue(oldType, out var existingNewType)) { throw new InvalidOperationException(string.Format( Strings.ExUnableToAssociateTypeXWithTypeYTypeXIsAlreadyMappedToTypeZ, oldType, newType, existingNewType)); } typeMapping[oldType] = newType; reverseTypeMapping[newType] = oldType; }
private bool EnsureTableExist(StoredTypeInfo type) { var nodeName = GetTableName(type); if (extractedStorageModel.Tables.Contains(nodeName)) { return(true); } UpgradeLog.Warning(Strings.ExTableXIsNotFound, nodeName); return(false); }
private static StoredTypeInfo[] GetAffectedMappedTypesAsArray(StoredTypeInfo type, bool includeInheritors) { var count = 1; var result = EnumerableUtils.One(type); if (includeInheritors) { result = result.Concat(type.AllDescendants); count += type.AllDescendants.Length; } return(type.Hierarchy.InheritanceSchema == InheritanceSchema.ConcreteTable ? result.Where(t => !t.IsAbstract).ToArray() : result.ToArray(count)); }
private static IEnumerable <StoredTypeInfo> GetAffectedMappedTypes(StoredTypeInfo type, bool includeInheritors) { var result = EnumerableUtils.One(type); if (includeInheritors) { result = result.Concat(type.AllDescendants); } if (type.Hierarchy.InheritanceSchema == InheritanceSchema.ConcreteTable) { result = result.Where(t => !t.IsAbstract); } return(result); }
private bool EnsureFieldExist(StoredTypeInfo type, string fieldName) { if (!EnsureTableExist(type)) { return(false); } var nodeName = GetTableName(type); var actualFieldName = nameBuilder.ApplyNamingRules(fieldName); if (extractedStorageModel.Tables[nodeName].Columns.Contains(actualFieldName)) { return(true); } UpgradeLog.Warning(Strings.ExColumnXIsNotFoundInTableY, actualFieldName, nodeName); return(false); }
private List <string> GetAffectedColumns(StoredTypeInfo type, StoredFieldInfo field) { var affectedColumns = new List <string>(); if (type.IsStructure) { var structureFields = extractedModel.Types .Where(t => t.IsEntity) .SelectMany(t => extractedModelFields[t].Where(f => f.IsStructure && f.ValueType == type.UnderlyingType)); foreach (var structureField in structureFields) { var nestedField = structureField.Fields.FirstOrDefault(f => f.OriginalName == field.Name); if (nestedField != null) { affectedColumns.AddRange(GetAffectedColumns(structureField.DeclaringType, nestedField)); } } return(affectedColumns); } foreach (var primitiveField in field.PrimitiveFields) { var inheritanceSchema = type.Hierarchy.InheritanceSchema; switch (inheritanceSchema) { case InheritanceSchema.ClassTable: affectedColumns.Add(GetColumnPath(primitiveField.DeclaringType, primitiveField.MappingName)); break; case InheritanceSchema.SingleTable: affectedColumns.Add(GetColumnPath(type.Hierarchy.Root, primitiveField.MappingName)); break; case InheritanceSchema.ConcreteTable: var columns = GetAffectedMappedTypes(type, true) .Select(t => GetColumnPath(t, primitiveField.MappingName)); affectedColumns.AddRange(columns); break; default: throw Exceptions.InternalError(String.Format(Strings.ExInheritanceSchemaIsInvalid, inheritanceSchema), UpgradeLog.Instance); } } return(affectedColumns); }
private void GenerateRenameFieldHint(StoredFieldInfo oldField, StoredFieldInfo newField, StoredTypeInfo newType, bool includeInheritors) { if (oldField.MappingName == newField.MappingName) { return; } foreach (var newTargetType in GetAffectedMappedTypes(newType, includeInheritors)) { StoredTypeInfo oldTargetType; if (!reverseTypeMapping.TryGetValue(newTargetType, out oldTargetType)) { continue; } RegisterRenameFieldHint(oldTargetType, newTargetType, oldField.MappingName, newField.MappingName); } }
private void GenerateCleanupByPrimaryKeyHints(StoredTypeInfo removedType, bool isMovedToAnotherHierarchy) { var hierarchy = removedType.Hierarchy; switch (hierarchy.InheritanceSchema) { case InheritanceSchema.ClassTable: IEnumerable <StoredTypeInfo> typesToProcess; typesToProcess = !isMovedToAnotherHierarchy ? EnumerableUtils.One(removedType).Concat(removedType.AllAncestors) : removedType.AllAncestors; foreach (var type in typesToProcess) { var identities1 = new[] { new IdentityPair( GetColumnPath(type, GetTypeIdMappingName(type)), removedType.TypeId.ToString(), true) }; schemaHints.Add( new DeleteDataHint(GetTablePath(type), identities1, isMovedToAnotherHierarchy)); } break; case InheritanceSchema.SingleTable: var rootType = hierarchy.Root; var identities2 = new[] { new IdentityPair( GetColumnPath(rootType, GetTypeIdMappingName(rootType)), removedType.TypeId.ToString(), true) }; schemaHints.Add( new DeleteDataHint(GetTablePath(rootType), identities2, isMovedToAnotherHierarchy)); break; case InheritanceSchema.ConcreteTable: // ConcreteTable schema doesn't include TypeId schemaHints.Add( new DeleteDataHint(GetTablePath(removedType), Array.Empty <IdentityPair>(), isMovedToAnotherHierarchy)); break; default: throw Exceptions.InternalError(string.Format(Strings.ExInheritanceSchemaIsInvalid, hierarchy.InheritanceSchema), UpgradeLog.Instance); } }
private void GenerateCleanupByPrimaryKeyHints(StoredTypeInfo removedType, bool isMovedToAnotherHierarchy) { var typesToProcess = new List <StoredTypeInfo>(); var hierarchy = removedType.Hierarchy; switch (hierarchy.InheritanceSchema) { case InheritanceSchema.ClassTable: if (!isMovedToAnotherHierarchy) { typesToProcess.Add(removedType); } typesToProcess.AddRange(removedType.AllAncestors); break; case InheritanceSchema.SingleTable: typesToProcess.Add(hierarchy.Root); break; case InheritanceSchema.ConcreteTable: typesToProcess.Add(removedType); break; default: throw Exceptions.InternalError(String.Format(Strings.ExInheritanceSchemaIsInvalid, hierarchy.InheritanceSchema), UpgradeLog.Instance); } foreach (var type in typesToProcess) { var sourceTablePath = GetTablePath(type); var identities = new List <IdentityPair>(); // ConcreteTable schema doesn't include TypeId if (hierarchy.InheritanceSchema != InheritanceSchema.ConcreteTable) { identities.Add(new IdentityPair( GetColumnPath(type, GetTypeIdMappingName(type)), removedType.TypeId.ToString(), true)); } schemaHints.Add( new DeleteDataHint(sourceTablePath, identities, isMovedToAnotherHierarchy)); } }
private bool IsMovedToAnotherHierarchy(StoredTypeInfo oldType) { var newType = typeMapping.GetValueOrDefault(oldType); if (newType == null) { return(false); // Type is removed } var oldRoot = oldType.Hierarchy.Root; if (oldRoot == null) { return(false); // Just to be sure } var newRoot = newType.Hierarchy.Root; if (newRoot == null) { return(false); // Just to be sure } return(newRoot != typeMapping.GetValueOrDefault(oldRoot)); }
private string GetTablePath(StoredTypeInfo type) { var nodeName = GetTableName(type); return(string.Format("Tables/{0}", nodeName)); }
private string GetTableName(StoredTypeInfo type) { return(resolver.GetNodeName( type.MappingDatabase, type.MappingSchema, type.MappingName)); }
private static string GetTablePath(this MappingResolver resolver, StoredTypeInfo type) { var nodeName = resolver.GetTableName(type); return(string.Format("Tables/{0}", nodeName)); }
private string GetTablePath(StoredTypeInfo type) => $"Tables/{GetTableName(type)}";
private static string GetTypeIdMappingName(StoredTypeInfo type) { return(type.AllFields .Single(field => field.Name.Equals(WellKnown.TypeIdFieldName, StringComparison.Ordinal)) .MappingName); }
private void BuildFieldMapping(IEnumerable <RenameFieldHint> renames, IEnumerable <ChangeFieldTypeHint> typeChanges, StoredTypeInfo oldType, StoredTypeInfo newType) { var newFields = newType.Fields.ToDictionary(field => field.Name); foreach (var oldField in oldType.Fields) { var renameHint = renames.FirstOrDefault(hint => hint.OldFieldName == oldField.Name && hint.TargetType.GetFullName() == newType.UnderlyingType); var newFieldName = renameHint != null ? renameHint.NewFieldName : oldField.Name; var newField = newFields.GetValueOrDefault(newFieldName); if (newField == null) { continue; } if (oldField.IsStructure) { // If it is structure, we map it immediately MapField(oldField, newField); continue; } var typeChangeHint = typeChanges .FirstOrDefault(hint => hint.Type.GetFullName() == newType.UnderlyingType && hint.FieldName == newField.Name); if (typeChangeHint == null) { // Check & skip field if type is changed var newValueTypeName = newField.IsEntitySet ? newField.ItemType : newField.ValueType; var oldValueTypeName = oldField.IsEntitySet ? oldField.ItemType : oldField.ValueType; var newValueType = currentTypes.GetValueOrDefault(newValueTypeName); var oldValueType = extractedTypes.GetValueOrDefault(oldValueTypeName); if (newValueType != null && oldValueType != null) { // We deal with reference field var mappedOldValueType = typeMapping.GetValueOrDefault(oldValueType); if (mappedOldValueType == null) { // Mapped to nothing = removed continue; } if (mappedOldValueType != newValueType && !newValueType.AllDescendants.Contains(mappedOldValueType)) { // This isn't a Dog -> Animal type mapping continue; } } else // We deal with regular field if (oldValueTypeName != newValueTypeName) { continue; } } MapField(oldField, newField); } }
public static string GetTableName(this MappingResolver resolver, StoredTypeInfo type) { return(resolver.GetNodeName( type.MappingDatabase, type.MappingSchema, type.MappingName)); }
private bool IsRemoved(StoredTypeInfo type) { return(!typeMapping.ContainsKey(type)); }
private static string GetTypeIdMappingName(StoredTypeInfo type) { var typeIdField = type.AllFields.Single(field => field.Name == WellKnown.TypeIdFieldName); return(typeIdField.MappingName); }
private void GenerateCleanupByForeignKeyHints(StoredTypeInfo removedType) { var removedTypeAndAncestors = removedType.AllAncestors.ToHashSet(); removedTypeAndAncestors.Add(removedType); var affectedAssociations = ( from association in extractedModel.Associations let requiresInverseCleanup = association.IsMaster && association.ConnectorType != null && removedTypeAndAncestors.Contains(association.ReferencingField.DeclaringType) where // Regular association X.Y, Y must be cleaned up removedTypeAndAncestors.Contains(association.ReferencedType) || // X.EntitySet<Y>, where X is in removedTypeAndAncestors, // connectorType.X must be cleaned up as well requiresInverseCleanup select new { association, requiresInverseCleanup } ).ToList(); foreach (var pair in affectedAssociations) { var association = pair.association; bool requiresInverseCleanup = pair.requiresInverseCleanup; if (association.ConnectorType == null) { // This is regular reference var field = association.ReferencingField; var declaringType = field.DeclaringType; if (declaringType.IsInterface) { var candidates = (extractedModel.Types.Where( t => !t.IsInterface && t.Fields.Any( f => f.IsInterfaceImplementation && f.Name == field.Name && f.ValueType == field.ValueType))) .ToList(); foreach (var candidate in candidates) { var inheritanceSchema = candidate.Hierarchy.InheritanceSchema; GenerateClearReferenceHints( removedType, GetAffectedMappedTypes(candidate, inheritanceSchema == InheritanceSchema.ConcreteTable).ToArray(), association, requiresInverseCleanup); } } else { var inheritanceSchema = declaringType.Hierarchy.InheritanceSchema; GenerateClearReferenceHints( removedType, GetAffectedMappedTypes(declaringType, inheritanceSchema == InheritanceSchema.ConcreteTable).ToArray(), association, requiresInverseCleanup); } } else { // This is EntitySet GenerateClearReferenceHints( removedType, new [] { association.ConnectorType }, association, requiresInverseCleanup); } } }