Example #1
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 #2
0
        internal void CreateTPHNotNullCheckConstraint(TableRef tblName, string colName, ObjectClass objClass)
        {
            // classes that do have this property
            var classes = objClass.AndChildren(c => c.SubClasses).Select(cls => Construct.DiscriminatorValue(cls)).ToList();

            // classes that do not have this property
            var otherClasses = objClass
                .BaseObjectClass // step once up, which is allowed, since we're not base (else isSimplyCheckable would be true) and necessary to let the skip work (see below)
                .AndParents(cls => cls.BaseObjectClass)
                .SelectMany(cls => cls
                    .AndChildren(c => c.SubClasses
                        .Where(child => child != objClass))) // skip self (and thus its children)
                .Select(cls => Construct.DiscriminatorValue(cls)).ToList();

            var checkExpressions = new Dictionary<List<string>, Expression<Func<string, bool>>>()
                    {
                        { classes, s => s != null },
                        { otherClasses, s => s == null },
                    };

            var checkConstraintName = Construct.CheckConstraintName(tblName.Name, colName);
            if (db.CheckCheckConstraintPossible(tblName, colName, checkConstraintName, checkExpressions))
            {
                try
                {
                    db.CreateCheckConstraint(tblName, colName, checkConstraintName, checkExpressions);
                }
                catch (Exception ex)
                {
                    // Don't abort on such a error
                    Log.ErrorFormat("unable to create CHECK constraint for ValueType Property '{0}' in '{1}': {2}", colName, tblName, ex.Message);
                }
            }
            else
                Log.ErrorFormat("unable to create CHECK constraint for ValueType Property '{0}' in '{1}': column contains invalid NULLs or superfluous values", colName, tblName);
        }
Example #3
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);
        }