protected virtual void ApplyPropertyMappings(ObjectClass cls) { if (cls.GetTableMapping() == TableMapping.TPH && cls.BaseObjectClass != null) { ApplyPropertyMappings(cls.BaseObjectClass); } var relevantRelations = cls.GetRelations() // Managed by a cache .Where(r => (r.A.Type.ID == cls.ID && r.Storage == StorageType.MergeIntoA) || (r.B.Type.ID == cls.ID && r.Storage == StorageType.MergeIntoB)) .ToList() .OrderBy(r => r.GetAssociationName()); foreach (var rel in relevantRelations) { string propertyName; string columnName; if (rel.A.Type == cls && rel.NeedsPositionStorage(RelationEndRole.A) && rel.A.Navigator != null) { propertyName = Construct.ListPositionPropertyName(rel.A); columnName = Construct.ListPositionColumnName(rel.B); this.WriteLine(" <ScalarProperty Name=\"{0}\" ColumnName=\"{1}\" />", propertyName, columnName); } if (rel.B.Type == cls && rel.NeedsPositionStorage(RelationEndRole.B) && rel.B.Navigator != null) { propertyName = Construct.ListPositionPropertyName(rel.B); columnName = Construct.ListPositionColumnName(rel.A); this.WriteLine(" <ScalarProperty Name=\"{0}\" ColumnName=\"{1}\" />", propertyName, columnName); } } foreach (var prop in cls.Properties.OfType<ValueTypeProperty>().Where(p => !p.IsList).OrderBy(p => p.Name)) { ModelMslEntityTypeMappingScalarProperty.Call(Host, ctx, prop, String.Empty); } foreach (var prop in cls.Properties.OfType<CompoundObjectProperty>().Where(p => !p.IsList).OrderBy(p => p.Name)) { ModelMslEntityTypeMappingComplexProperty.Call(Host, ctx, prop, String.Empty); } }
public static object[] MakeArgs(IZetboxContext ctx, ObjectClass cls, NameValueCollection templateSettings) { if (ctx == null) { throw new ArgumentNullException("ctx"); } if (cls == null) { throw new ArgumentNullException("cls"); } if (templateSettings == null) { throw new ArgumentNullException("templateSettings"); } string extraSuffix = templateSettings["extrasuffix"]; string interfaceName = cls.Name; string implementationName = cls.Name + extraSuffix + Zetbox.API.Helper.ImplementationSuffix; string schemaName = cls.Module.SchemaName; string tableName = cls.TableName; string qualifiedImplementationName = GetAssemblyQualifiedProxy(cls, templateSettings); bool isAbstract = cls.IsAbstract; List<Property> properties = cls.Properties.ToList(); List<ObjectClass> subClasses = cls.SubClasses.ToList(); bool needsRightTable = Templates.ObjectClasses.Template.NeedsRightsTable(cls); string qualifiedRightsClassName = cls.Module.Namespace + "." + Construct.SecurityRulesClassName(cls) + extraSuffix + Zetbox.API.Helper.ImplementationSuffix + ", Zetbox.Objects." + extraSuffix + Zetbox.API.Helper.ImplementationSuffix; bool needsConcurrency = cls.ImplementsIChangedBy(true); return new object[] { interfaceName, implementationName, schemaName, tableName, qualifiedImplementationName, isAbstract, properties, subClasses, needsRightTable, needsConcurrency, qualifiedRightsClassName, cls.GetTableMapping() }; }
private void CheckColumns(ObjectClass objClass, ICollection<Property> properties, string prefix) { Log.Debug(" Columns: "); var tblName = objClass.GetTableRef(db); var mapping = objClass.GetTableMapping(); if (mapping == TableMapping.TPH && objClass.BaseObjectClass == null) { CheckColumn(tblName, TableMapper.DiscriminatorColumnName, System.Data.DbType.String, TableMapper.DiscriminatorColumnSize, 0, false, null); } foreach (ValueTypeProperty prop in properties.OfType<ValueTypeProperty>() .Where(p => !p.IsList) .OrderBy(p => p.Module.Namespace).ThenBy(p => p.Name)) { var colName = Construct.ColumnName(prop, prefix); Log.DebugFormat(" {0}", colName); var realIsNullable = prop.IsNullable(); if (realIsNullable == false) realIsNullable = mapping == TableMapping.TPH && objClass.BaseObjectClass != null; CheckColumn(tblName, colName, prop.GetDbType(), prop.GetSize(), prop.GetScale(), realIsNullable, SchemaManager.GetDefaultConstraint(prop)); } foreach (CompoundObjectProperty sprop in properties.OfType<CompoundObjectProperty>().Where(p => !p.IsList)) { CheckColumns(objClass, sprop.CompoundObjectDefinition.Properties, Construct.ColumnName(sprop, prefix)); } }
private void CheckExtraColumns(ObjectClass objClass) { if (objClass.GetTableMapping() == TableMapping.TPH && objClass.BaseObjectClass != null) return; // Check only base TPH classes Log.Debug("Extra Columns: "); List<string> columns = new List<string>(); List<ObjectClass> classes = new List<ObjectClass>(new[] { objClass }); if (objClass.GetTableMapping() == TableMapping.TPH) objClass.CollectChildClasses(classes, true); foreach (var cls in classes) { GetExistingColumnNames(cls, cls.Properties, String.Empty, columns); GetRelationColumnNames(cls, columns); } foreach (string propName in db.GetTableColumnNames(objClass.GetTableRef(db))) { if (propName == "ID" || propName == TableMapper.DiscriminatorColumnName) continue; if (!columns.Contains(propName)) { Log.WarnFormat("Column '[{0}].[{1}].[{2}]' found in database but no Property was defined", objClass.Module.IfNotNull(o => o.SchemaName), objClass.TableName, propName); } } }
public bool IsChangeTphToTpt(ObjectClass objClass) { // only migrate on the RootClass if (objClass.BaseObjectClass != null) return false; ObjectClass savedObjClass = savedSchema.FindPersistenceObject<ObjectClass>(objClass.ExportGuid); if (savedObjClass == null) return false; return savedObjClass.GetTableMapping() == TableMapping.TPH && objClass.GetTableMapping() == TableMapping.TPT; }
public bool IsChangeTptToTph(ObjectClass objClass) { ObjectClass savedObjClass = savedSchema.FindPersistenceObject<ObjectClass>(objClass.ExportGuid); if (savedObjClass == null) return false; return savedObjClass.GetTableMapping() == TableMapping.TPT && objClass.GetTableMapping() == TableMapping.TPH; }
public void DoRenameObjectClassTable(ObjectClass objClass) { var savedObjClass = savedSchema.FindPersistenceObject<ObjectClass>(objClass.ExportGuid); if (!PreMigration(ClassMigrationEventType.RenameTable, savedObjClass, objClass)) return; var tbl = objClass.GetTableRef(db); var saveTbl = savedObjClass.GetTableRef(db); Log.InfoFormat("Renaming table from '{0}' to '{1}'", saveTbl, tbl); var mapping = objClass.GetTableMapping(); if (mapping == TableMapping.TPT || (mapping == TableMapping.TPH && objClass.BaseObjectClass == null)) { db.RenameTable(saveTbl, tbl); } else if (mapping == TableMapping.TPH && objClass.BaseObjectClass != null) { foreach (var prop in objClass.Properties.OfType<ValueTypeProperty>().Where(p => !p.IsList)) { DoRenameValueTypePropertyName(objClass, prop, string.Empty); } // FK names will be changed in DoChangeRelationName case } if (mapping == TableMapping.TPH) { db.RenameDiscriminatorValue(tbl, Construct.DiscriminatorValue(savedObjClass), Construct.DiscriminatorValue(objClass)); } PostMigration(ClassMigrationEventType.RenameTable, savedObjClass, objClass); }
public void DoNewValueTypePropertyNotNullable(ObjectClass objClass, ValueTypeProperty prop, string prefix) { if (!PreMigration(PropertyMigrationEventType.Add, null, prop)) return; var tblName = objClass.GetTableRef(db); var colName = Construct.ColumnName(prop, prefix); var dbType = prop.GetDbType(); var size = prop.GetSize(); var scale = prop.GetScale(); var def = SchemaManager.GetDefaultConstraint(prop); var isSimplyCheckable = objClass.GetTableMapping() == TableMapping.TPT || objClass.BaseObjectClass == null; bool updateDone = false; // classes that do have this property var classes = objClass.AndChildren(c => c.SubClasses).Select(cls => Construct.DiscriminatorValue(cls)).ToList(); Log.InfoFormat("New not nullable ValueType Property: [{0}.{1}] (col:{2})", prop.ObjectClass.Name, prop.Name, colName); CheckValueTypePropertyHasWarnings(prop); if (db.CheckTableContainsData(tblName, isSimplyCheckable ? null : classes)) { db.CreateColumn(tblName, colName, dbType, size, scale, true, isSimplyCheckable ? def : null); updateDone = WriteDefaultValue(tblName, colName, def, isSimplyCheckable ? null : classes); } else { db.CreateColumn(tblName, colName, dbType, size, scale, !isSimplyCheckable, isSimplyCheckable ? def : null); updateDone = true; } if (updateDone && isSimplyCheckable) { db.AlterColumn(tblName, colName, dbType, size, scale, false, def); } else if (updateDone && !isSimplyCheckable) { CreateTPHNotNullCheckConstraint(tblName, colName, objClass); } else if (!updateDone && isSimplyCheckable) { Log.ErrorFormat("unable to set ValueType Property '{0}' to NOT NULL when table '{1}' contains data: No supported default constraint found", colName, tblName); } else if (!updateDone && !isSimplyCheckable) { Log.ErrorFormat("unable to create CHECK constraint on ValueType Property '{0}' when table '{1}' contains data: No supported default constraint found", colName, tblName); } PostMigration(PropertyMigrationEventType.Add, null, prop); }
public void DoNewObjectClass(ObjectClass objClass) { if (!PreMigration(ClassMigrationEventType.Add, null, objClass)) return; TableMapping mapping = objClass.GetTableMapping(); if (mapping == TableMapping.TPT || (mapping == TableMapping.TPH && objClass.BaseObjectClass == null)) { var tblName = objClass.GetTableRef(db); Log.InfoFormat("New Table: {0}", tblName); if (!db.CheckTableExists(tblName)) { db.CreateTable(tblName, objClass.BaseObjectClass == null); if (mapping == TableMapping.TPH) { db.CreateColumn(tblName, TableMapper.DiscriminatorColumnName, System.Data.DbType.String, TableMapper.DiscriminatorColumnSize, 0, false); } } else { Log.ErrorFormat("Table {0} already exists", tblName); } } else { Log.DebugFormat("Skipping table for TPH child {0}", objClass.Name); } PostMigration(ClassMigrationEventType.Add, null, objClass); }
public void DoDeleteObjectClass(ObjectClass savedObjClass) { if (!PreMigration(ClassMigrationEventType.Delete, savedObjClass, null)) return; if (savedObjClass.NeedsRightsTable()) { DoDeleteObjectClassSecurityRules(savedObjClass); } foreach (var lstPop in savedObjClass.Properties.OfType<ValueTypeProperty>().Where(p => p.IsList)) { DoDeleteValueTypePropertyList(savedObjClass, lstPop, string.Empty); } foreach (var lstPop in savedObjClass.Properties.OfType<CompoundObjectProperty>().Where(p => p.IsList)) { DoDeleteCompoundObjectPropertyList(savedObjClass, lstPop, string.Empty); } var mapping = savedObjClass.GetTableMapping(); if (mapping == TableMapping.TPT) { var tbl = savedObjClass.GetTableRef(db); Log.InfoFormat("Drop Table: {0}", tbl); if (db.CheckTableExists(tbl)) db.DropTable(tbl); } else if (mapping == TableMapping.TPH) { // TODO: Do delete all columns } else { throw new NotSupportedException(string.Format("Mapping {0} is not supported", mapping)); } PostMigration(ClassMigrationEventType.Delete, savedObjClass, null); }
public void DoChangeValueTypeProperty_To_NotNullable(ObjectClass objClass, ValueTypeProperty prop, string prefix) { var savedProp = savedSchema.FindPersistenceObject<ValueTypeProperty>(prop.ExportGuid); if (!PreMigration(PropertyMigrationEventType.ChangeToNotNullable, savedProp, prop)) return; var tblName = objClass.GetTableRef(db); var colName = Construct.ColumnName(prop, prefix); var def = SchemaManager.GetDefaultConstraint(prop); if (def == null && db.CheckColumnContainsNulls(tblName, colName)) { Log.ErrorFormat("column '{0}.{1}' contains NULL values and has no default contraint, cannot set NOT NULLABLE", tblName, colName); } else { if (def != null) { var isSimplyCheckable = objClass.GetTableMapping() == TableMapping.TPT || objClass.BaseObjectClass == null; var classes = objClass.AndChildren(c => c.SubClasses).Select(cls => Construct.DiscriminatorValue(cls)).ToList(); WriteDefaultValue(tblName, colName, def, isSimplyCheckable ? null : classes); } db.AlterColumn(tblName, colName, prop.GetDbType(), prop.GetSize(), prop.GetScale(), prop.IsNullable(), null /* don't change contraints */); } PostMigration(PropertyMigrationEventType.ChangeToNotNullable, savedProp, prop); }