/// <summary> /// 尝试同步表,有可能不成功 /// </summary> /// <param name="table"></param> private void SyncTable(ITableContext table) { bool hasRow = this.TableHasRow(table.Name); //表肯定存在,就看列存不存在 //最简单的迁移策略: //如果列在表里不存在就建,以用户定义的为准 //列元属性同步策略: //* 类型相同可以更改长度,其实也就是 varchar 可以 //* 可空转非空:检测表里是否有行,有的话要求此字段有默认值,更改之前先用默认值填充 // 现有行再转换为非空 //* 非空转可控:可以直接去掉 NOT NULL //先处理代码里定义的列 foreach (var pair in this.model.Fields) { var field = pair.Value; if (field.IsColumn) { if (!table.ColumnExists(field.Name)) { table.AddColumn(this.context.DataContext, field); } else { this.SyncColumn(table, field, hasRow); } } } //然后处理数据库里存在,但代码里未定义的列 //处理策略很简单,我们的原则是不能删除用户的数据,如果是空表直接删除该列,如果有数据就把该列设成可空 var columns = table.GetAllColumns(); var columnsToDelete = columns.Select(c => c.Name) .Except(this.model.Fields.Select(f => f.Value.Name)); //删除数据库存在,但代码未定义的 if (hasRow) { foreach (var c in columns) { if (!c.Nullable && columnsToDelete.Contains(c.Name)) { table.AlterColumnNullable(this.context.DataContext, c.Name, true); } } } else { foreach (var c in columnsToDelete) { table.DeleteColumn(this.context.DataContext, c); } } }
private void SetColumnNotNullable(ITableContext table, IField field, bool hasRow) { //先看有没有行,有行要先设置默认值,如果没有默认值就报错了 if (hasRow && field.DefaultProc != null) { var defaultValue = field.DefaultProc(this.context); var sql = string.Format(CultureInfo.InvariantCulture, "update \"{0}\" set \"{1}\"=?", table.Name, field.Name); this.context.DataContext.Execute(sql, defaultValue); table.AlterColumnNullable(this.context.DataContext, field.Name, false); } else { LoggerProvider.EnvironmentLogger.Warn(() => string.Format( "Unable alter table '{0}' column '{1}' to not nullable", table.Name, field.Name)); } }
private void SetColumnNullable(ITableContext table, IField field) { table.AlterColumnNullable(this.context.DataContext, field.Name, true); }