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);
            }
        }
Example #2
0
        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);
                }
            }
        }
Example #5
0
        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;
        }
Example #6
0
        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;
        }
Example #7
0
        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);
        }
Example #8
0
        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);
        }
Example #9
0
        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);
        }
Example #10
0
        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);
        }
Example #11
0
        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);
        }