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(); } } }
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; } }
/// <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); }
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; }
public ColumnChanges(Column oldColumn, Column newColumn, ChangeType changeType) { this.OldColumn = oldColumn; this.NewColumn = newColumn; this.ChangeType = changeType; }
/// <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); }
/// <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 ); } }
/// <summary> /// /// </summary> /// <param name="primaryKeyColumn">这个外键对应的主键表的列(不一定是主键列,可以是unique列等)</param> public ForeignConstraint(Column primaryKeyColumn) { if (primaryKeyColumn == null) throw new ArgumentNullException("primaryKeyColumn"); this.PKColumn = primaryKeyColumn; }
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 }); }); } }
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, }); } }
/// <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; }
/// <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 } } }