Пример #1
0
        protected override void LoadAllColumns(Database database)
        {
            foreach (Table table in database.Tables)
            {
                using (var columnsReader = this.Db.QueryDataReader(@"
            SELECT * FROM user_tab_columns WHERE TABLE_NAME = {0}
            ", table.Name))
                {
                    while (columnsReader.Read())
                    {
                        string columnName = columnsReader["COLUMN_NAME"].ToString();
                        string sqlType = columnsReader["DATA_TYPE"].ToString().ToLower();
                        if (sqlType == "number")
                        {
                            var dataScale = columnsReader["DATA_SCALE"].ToString();
                            if (dataScale == "0") { sqlType = "integer"; }
                        }

                        DbType dbType = OracleDbTypeHelper.ConvertFromOracleTypeString(sqlType);
                        Column column = new Column(dbType, null, columnName, table);
                        column.IsRequired = columnsReader["NULLABLE"].ToString() == "N";

                        table.Columns.Add(column);
                    }

                    table.SortColumns();
                }
            }
        }
Пример #2
0
 public static bool Equals(Column a, Column b)
 {
     if (a.Table.Name.EqualsIgnoreCase(b.Table.Name) &&
         a.Name.EqualsIgnoreCase(b.Name) &&
         a.DataType == b.DataType &&
         a.IsRequired == b.IsRequired &&
         a.IsForeignKey == b.IsForeignKey &&
         a.IsPrimaryKey == b.IsPrimaryKey
         )
     {
         //判断外键是否相等
         //暂时不考虑NeedDeleteCascade是否相同的问题
         if (a.IsForeignKey &&
             !a.ForeignConstraint.PKColumn.Table.Name.Equals(b.ForeignConstraint.PKColumn.Table.Name))
         {
             return false;
         }
         else
         {
             return true;
         }
     }
     else
     {
         return false;
     }
 }
Пример #3
0
        /// <summary>
        /// 加载每个表的所有列
        /// </summary>
        /// <param name="database"></param>
        protected override void LoadAllColumns(Database database)
        {
            foreach (Table table in database.Tables)
            {
                using (var columnsReader = this.Db.QueryDataReader(@"
            SELECT C.COLUMN_NAME, C.IS_NULLABLE, C.DATA_TYPE, C.CHARACTER_MAXIMUM_LENGTH
            FROM INFORMATION_SCHEMA.COLUMNS C
            WHERE C.TABLE_NAME = {0}
            ", table.Name))
                {
                    while (columnsReader.Read())
                    {
                        string columnName = columnsReader["COLUMN_NAME"].ToString();
                        string sqlType = columnsReader["DATA_TYPE"].ToString();

                        //不再读取 Length
                        //string length = null;
                        //var lengthObj = columnsReader["CHARACTER_MAXIMUM_LENGTH"];
                        //if (lengthObj != null && !DBNull.Value.Equals(lengthObj) && lengthObj.ToString() != "-1")
                        //{
                        //    length = lengthObj.ToString();
                        //}

                        DbType dbType = SqlDbTypeHelper.ConvertFromSQLTypeString(sqlType);
                        Column column = new Column(dbType, null, columnName, table);

                        column.IsRequired = string.Compare(columnsReader["IS_NULLABLE"].ToString(), "no", true) == 0;

                        table.Columns.Add(column);
                    }

                    table.SortColumns();
                }
            }

            this.LoadIsIdentity(database);
        }
Пример #4
0
        private static ColumnChanges Distinguish(Column oldColumn, Column newColumn)
        {
            //if (newColumn == null) throw new ArgumentNullException("newColumn");
            //if (newColumn.Name.EqualsIgnoreCase(oldColumn.Name)) throw new InvalidOperationException("newColumn.Name.EqualsIgnoreCase(oldColumn.Name) must be false.");
            //if (newColumn.Table.Name.EqualsIgnoreCase(oldColumn.Table.Name)) throw new InvalidOperationException("newColumn.Table.Name.EqualsIgnoreCase(oldColumn.Table.Name) must be false.");

            ColumnChanges columnChanged = null;
            if (!Equals(newColumn, oldColumn))
            {
                columnChanged = new ColumnChanges(oldColumn, newColumn, ChangeType.Modified);

                if (newColumn.IsRequired != oldColumn.IsRequired) { columnChanged.IsRequiredChanged = true; }

                if (newColumn.IsPrimaryKey != oldColumn.IsPrimaryKey) { columnChanged.IsPrimaryKeyChanged = true; }

                if (newColumn.DataType != oldColumn.DataType) { columnChanged.IsDbTypeChanged = true; }

                //ForeignRelationChangeType
                columnChanged.ForeignRelationChangeType = ChangeType.UnChanged;
                if (!newColumn.IsForeignKey && oldColumn.IsForeignKey)
                {
                    columnChanged.ForeignRelationChangeType = ChangeType.Removed;
                }
                else if (newColumn.IsForeignKey && !oldColumn.IsForeignKey)
                {
                    columnChanged.ForeignRelationChangeType = ChangeType.Added;
                }
                else if (newColumn.IsForeignKey && oldColumn.IsForeignKey)
                {
                    if (!Equals(newColumn.ForeignConstraint, oldColumn.ForeignConstraint))
                    {
                        columnChanged.ForeignRelationChangeType = ChangeType.Modified;
                    }
                }
            }
            return columnChanged;
        }
Пример #5
0
 public ColumnChanges(Column oldColumn, Column newColumn, ChangeType changeType)
 {
     this.OldColumn = oldColumn;
     this.NewColumn = newColumn;
     this.ChangeType = changeType;
 }
Пример #6
0
            /// <summary>
            /// 根据实体类型创建表的描述信息,并添加到数据库中
            /// </summary>
            /// <param name="em">The memory.</param>
            /// <exception cref="System.ArgumentNullException"></exception>
            /// <exception cref="System.InvalidOperationException">refMeta.ReferenceInfo == null</exception>
            private void BuildTable(EntityMeta em)
            {
                var tableMeta = em.TableMeta;

                //视图类不需要支持数据库迁移。
                if (tableMeta.IsMappingView) { return; }

                var table = new Table(tableMeta.TableName, this.Database);

                var metaProperties = em.EntityProperties;

                //var managedProperties = ManagedPropertyRepository.Instance
                //    .GetTypePropertiesContainer(em.EntityType)
                //    .GetNonReadOnlyCompiledProperties();

                foreach (var property in metaProperties)
                {
                    var columnMeta = property.ColumnMeta;
                    if (columnMeta == null) continue;

                    var mp = property.ManagedProperty;
                    if (mp == null) { throw new ArgumentNullException(string.Format("{0}.{1} 属性需要使用托管属性进行编写。", em.Name, mp.Name)); }

                    //列名
                    var propertyName = property.Name;
                    var columnName = columnMeta.ColumnName;
                    if (string.IsNullOrWhiteSpace(columnName)) columnName = propertyName;

                    //类型
                    var propertyType = property.PropertyType;
                    bool isNullableRef = false;

                    #region 引用关系

                    if (columnMeta.HasFKConstraint)
                    {
                        var refProperty = mp as IRefProperty;
                        if (refProperty != null)
                        {
                            isNullableRef = refProperty.Nullable;

                            var refMeta = em.Property(refProperty.RefEntityProperty);
                            if (refMeta.ReferenceInfo == null) throw new InvalidOperationException("refMeta.ReferenceInfo == null");

                            //引用实体的类型。
                            var refTypeMeta = refMeta.ReferenceInfo.RefTypeMeta;
                            if (refTypeMeta != null)
                            {
                                var refTableMeta = refTypeMeta.TableMeta;
                                if (refTableMeta != null)
                                {
                                    //如果主键表已经被忽略,那么到这个表上的外键也不能建立了。
                                    //这是因为被忽略的表的结构是未知的,不一定是以这个字段为主键。
                                    if (!this.Database.IsIgnored(refTableMeta.TableName))
                                    {
                                        var id = refTypeMeta.Property(Entity.IdProperty);
                                        //有时一些表的 Id 只是自增长,但并不是主键,不能创建外键。
                                        if (id.ColumnMeta.IsPrimaryKey)
                                        {
                                            this._foreigns.Add(new ForeignConstraintInfo()
                                            {
                                                FkTableName = tableMeta.TableName,
                                                PkTableName = refTableMeta.TableName,
                                                FkColumn = columnName,
                                                PkColumn = id.ColumnMeta.ColumnName,
                                                NeedDeleteCascade = refProperty.ReferenceType == ReferenceType.Parent
                                            });
                                        }
                                    }
                                }
                            }
                        }
                        else if (mp == Entity.TreePIdProperty)
                        {
                            var id = em.Property(Entity.IdProperty);
                            //有时一些表的 Id 只是自增长,但并不是主键,不能创建外键。
                            if (id.ColumnMeta.IsPrimaryKey)
                            {
                                this._foreigns.Add(new ForeignConstraintInfo()
                                {
                                    FkTableName = tableMeta.TableName,
                                    PkTableName = tableMeta.TableName,
                                    FkColumn = columnName,
                                    PkColumn = id.ColumnMeta.ColumnName,
                                    NeedDeleteCascade = false
                                });
                            }
                        }
                    }

                    #endregion

                    var dataType = TypeHelper.IgnoreNullable(propertyType);
                    //对于支持多数据类型的 Id、TreePId 属性进行特殊处理。
                    if (mp == Entity.IdProperty || mp == Entity.TreePIdProperty)
                    {
                        dataType = em.IdType;
                    }
                    var dbType = columnMeta.DataType.GetValueOrDefault(DbTypeHelper.ConvertFromCLRType(dataType));
                    var column = new Column(dbType, columnMeta.DataTypeLength, columnName, table);
                    if (columnMeta.IsRequired.HasValue)
                    {
                        column.IsRequired = columnMeta.IsRequired.Value;
                    }
                    else
                    {
                        column.IsRequired = !isNullableRef && !propertyType.IsClass && !TypeHelper.IsNullable(propertyType);
                    }
                    //IsPrimaryKey 的设置放在 IsRequired 之后,可以防止在设置可空的同时把列调整为非主键。
                    column.IsPrimaryKey = columnMeta.IsPrimaryKey;
                    column.IsIdentity = columnMeta.IsIdentity;

                    table.Columns.Add(column);
                }

                table.SortColumns();

                this.AddTable(table);
            }
Пример #7
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fkColumn">这个列的外键</param>
        internal void Init(Column fkColumn)
        {
            if (fkColumn == null) throw new ArgumentNullException("fkColumn");
            this.FKColumn = fkColumn;

            if (string.IsNullOrWhiteSpace(this.ConstraintName))
            {
                this.ConstraintName = string.Format(
                    "FK_{0}_{1}_{2}_{3}",
                    this.FKColumn.Table.Name,
                    this.FKColumn.Name,
                    this.PKColumn.Table.Name,
                    this.PKColumn.Name
                    );
            }
        }
Пример #8
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="primaryKeyColumn">这个外键对应的主键表的列(不一定是主键列,可以是unique列等)</param>
 public ForeignConstraint(Column primaryKeyColumn)
 {
     if (primaryKeyColumn == null) throw new ArgumentNullException("primaryKeyColumn");
     this.PKColumn = primaryKeyColumn;
 }
Пример #9
0
        private void AddColumn(Column column)
        {
            this.AddOperation(new CreateNormalColumn
            {
                CopyFromColumn = column,
                IsPrimaryKey = column.IsPrimaryKey,
                IsIdentity = column.IsIdentity,
            });

            //自增列必然是不可空的,在创建列时已经同时把不可空约束给创建好了,所以这里不需要重复添加了。
            if (column.IsRequired && !column.IsIdentity)
            {
                this.AddOperation(new AddNotNullConstraint
                {
                    CopyFromColumn = column,
                });
            }

            if (column.IsForeignKey)
            {
                this.AddRelationAction(() =>
                {
                    this.AddOperation(new AddFKConstraint
                    {
                        CopyFromConstraint = column.ForeignConstraint
                    });
                });
            }
        }
Пример #10
0
        private void RemoveColumn(Column column)
        {
            if ((Context.RunDataLossOperation & DataLossOperation.DropColumn) != 0)
            {
                Context.NotifyDataLoss("删除列");

                if (column.IsForeignKey)
                {
                    this.AddOperation(new RemoveFKConstraint
                    {
                        CopyFromConstraint = column.ForeignConstraint
                    });
                }

                if (column.IsRequired)
                {
                    this.AddOperation(new RemoveNotNullConstraint
                    {
                        CopyFromColumn = column,
                    });
                }

                this.AddOperation(new DropNormalColumn
                {
                    CopyFromColumn = column,
                    IsPrimaryKey = column.IsPrimaryKey,
                    IsIdentity = column.IsIdentity,
                });
            }
        }
Пример #11
0
        /// <summary>
        /// 添加一列到这个表中。
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="type">The type.</param>
        /// <param name="length">The length.</param>
        /// <param name="isRequired">if set to <c>true</c> [is required].</param>
        /// <param name="isPrimaryKey">if set to <c>true</c> [is primary key].</param>
        /// <param name="foreignConstraint">The foreign constraint.</param>
        /// <returns></returns>
        public Column AddColumn(string name, DbType type,
            string length = null,
            bool isRequired = false,
            bool isPrimaryKey = false,
            ForeignConstraint foreignConstraint = null
            )
        {
            var column = new Column(type, length, name, this)
            {
                IsRequired = isRequired,
                IsPrimaryKey = isPrimaryKey,
                ForeignConstraint = foreignConstraint
            };

            this.Columns.Add(column);

            return column;
        }
Пример #12
0
        /// <summary>
        /// 处理主键和外键
        /// </summary>
        /// <param name="column"></param>
        /// <param name="allConstraints">所有的约束</param>
        private void DealColumnConstraints(Column column, IList<Constraint> allConstraints)
        {
            var database = column.Table.DataBase;

            var constraints = allConstraints.Where(c => c.COLUMN_NAME == column.Name && c.TABLE_NAME == column.Table.Name).ToList();

            foreach (var constraint in constraints)
            {
                //主键
                if (string.Compare(constraint.CONSTRAINT_TYPE, "PRIMARY KEY", true) == 0)
                {
                    column.IsPrimaryKey = true;
                }
                else if (string.Compare(constraint.CONSTRAINT_TYPE, "FOREIGN KEY", true) == 0)
                {
                    #region 外键

                    bool deleteCascade = string.Compare(constraint.DELETE_RULE, "CASCADE", true) == 0;
                    var pkTable = database.FindTable(constraint.PK_TABLE_NAME);
                    if (pkTable == null) throw new ArgumentNullException("pkTable");
                    var pkColumn = pkTable.FindColumn(constraint.PK_COLUMN_NAME);

                    column.ForeignConstraint = new ForeignConstraint(pkColumn)
                    {
                        NeedDeleteCascade = deleteCascade,
                        ConstraintName = constraint.CONSTRAINT_NAME
                    };

                    #endregion
                }
            }
        }