예제 #1
0
 public TableChanges(Table oldTable, Table newTable, ChangeType changeType)
 {
     this.OldTable = oldTable;
     this.NewTable = newTable;
     this.ChangeType = changeType;
     this.ColumnsChanged = new List<ColumnChanges>();
 }
예제 #2
0
파일: Column.cs 프로젝트: hardCTE/Rafy
        /// <summary>
        /// Initializes a new instance of the <see cref="Column"/> class.
        /// </summary>
        /// <param name="name">列名.</param>
        /// <param name="dataType">数据类型.</param>
        /// <param name="length">见 <see cref="Length"/> 属性.</param>
        /// <param name="table">所在表.</param>
        /// <exception cref="System.ArgumentNullException">
        /// DataTable
        /// or
        /// name
        /// </exception>
        public Column(string name, DbType dataType, string length, Table table)
        {
            if (table == null) throw new ArgumentNullException("DataTable");
            if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullException("name");

            this.DataType = dataType;
            this.Length = length;
            this.Name = name;
            this.Table = table;
        }
예제 #3
0
        protected override void LoadAllTables(Database database)
        {
            using (var reader = this.Db.QueryDataReader(@"select * from user_tables"))
            {
                while (reader.Read())
                {
                    string tableName = reader["TABLE_NAME"].ToString();

                    Table table = new Table(tableName, database);

                    database.Tables.Add(table);
                }
            }
        }
예제 #4
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);
            }
예제 #5
0
 /// <summary>
 /// 将表添加到数据库中,对于已经存在的表进行全并
 /// </summary>
 /// <param name="table"></param>
 private void AddTable(Table table)
 {
     var existingTable = this.Database.FindTable(table.Name);
     if (existingTable != null)
     {
         //由于有类的继承关系存在,合并两个表的所有字段。
         foreach (var newColumn in table.Columns)
         {
             if (existingTable.FindColumn(newColumn.Name) == null)
             {
                 existingTable.Columns.Add(newColumn);
             }
         }
     }
     else
     {
         this.Database.Tables.Add(table);
     }
 }
예제 #6
0
        /// <summary>
        /// 添加所有表
        /// </summary>
        /// <param name="database"></param>
        protected override void LoadAllTables(Database database)
        {
            using (var reader = this.Db.QueryDataReader(@"select * from INFORMATION_SCHEMA.TABLES"))
            {
                while (reader.Read())
                {
                    string tableName = reader["TABLE_NAME"].ToString();
                    string tableType = reader["TABLE_TYPE"].ToString().ToLower();

                    //SqlServer 中是 "BASE TABLE",同时还会把一些系统表也查询出来,例如:sysdiagrams
                    //SQLCE 中是 "TABLE"
                    if (tableType.Contains("table") && !tableName.StartsWith("sys"))
                    {
                        //string schemaName = reader["SCHEMA_NAME"].ToString();

                        Table table = new Table(tableName, database);

                        database.Tables.Add(table);
                    }
                }
            }
        }
예제 #7
0
 private string ToEntityName(Table table)
 {
     var name = table.Name;
     if (name.EndsWith("s"))
     {
         if (name.EndsWith("aes") ||
             name.EndsWith("oes") ||
             name.EndsWith("ees") ||
             name.EndsWith("ies") ||
             name.EndsWith("ues"))
         {
             //支持 es 后缀
             name = name.Substring(0, name.Length - 2);
         }
         else
         {
             //支持 s 后缀
             name = name.Substring(0, name.Length - 1);
         }
     }
     return name;
 }
예제 #8
0
        private void RemoveTable(Table table)
        {
            if ((Context.RunDataLossOperation & DataLossOperation.DropTable) != 0)
            {
                Context.NotifyDataLoss("删除表");

                foreach (var column in table.FindNormalColumns())
                {
                    this.RemoveColumn(column);
                }

                this.AddOperation(new DropTable
                {
                    CopyFromTable = table
                });
            }
        }
예제 #9
0
        private Column RenderId(Table table)
        {
            var identites = FindIdentityColumns(table);
            foreach (var identity in identites)
            {
                //这个属性则直接映射 Entity.Id 属性,不需要添加任何代码。
                //同时,如果在 Id 字样之前还有其它字母,则需要添加字段映射。
                if (identity.Name.ToLower() != "id")
                {
                    _tablePropertiesConfig.Add(new PropertyConfig
                    {
                        PropertyName = "Id",
                        ColumnName = identity.Name,
                        ClearIdPrimaryKey = !identity.IsPrimaryKey
                    });
                }

                //前面已经用 CheckHasPK 方法进行检测,所以必然有且只有一个字段满足这个条件,直接退出循环。
                return identity;
            }

            //之前已经用 CheckHasPK 方法检测过,这一行代码不可能到达。
            throw new NotSupportedException("未知错误。");
        }
예제 #10
0
        private string RenderColumnConfig(Table table)
        {
            var code = new StringBuilder();

            foreach (var config in _tablePropertiesConfig)
            {
                code.AppendFormat(@"
            Meta.Property({0}.{1}Property).MapColumn().HasColumnName(""{2}"")",
                    ToEntityName(table), config.PropertyName, config.ColumnName
                    );
                if (config.ClearIdPrimaryKey)
                {
                    code.Append(@".IsPrimaryKey(false)");
                }
                code.Append(';');
            }

            return code.ToString();
        }
예제 #11
0
        private bool GenerateRepoFile(Table table)
        {
            var entityName = ToEntityName(table);
            var fileName = entityName + "Repository.cs";
            var item = _repoDirectory.ProjectItems.FindByName(fileName);
            if (item != null) return false;

            _tablePropertiesConfig.Clear();

            //使用模板格式化字符串。
            var code = ItemCodeTemplate.GetRepositoryFileCode(
                this.DomainName, this.DomainName + ".Repositories", entityName, _domainBaseEntityName
                );

            //写到文件,并加入到项目中。
            var file = Path.Combine(Path.GetDirectoryName(_repoDirectory.get_FileNames(1)), fileName);
            File.WriteAllText(file, code);
            _repoDirectory.ProjectItems.AddFromFile(file);
            return true;
        }
예제 #12
0
        private bool GenerateClassFile(Table table)
        {
            if (table.Name == "zzzDbMigrationVersion") return false;

            var entityName = ToEntityName(table);
            var fileName = entityName + ".cs";
            var item = _directory.ProjectItems.FindByName(fileName);
            if (item != null) return false;

            if (!CheckHasPK(table)) return false;

            _tablePropertiesConfig.Clear();

            var parameters = new ItemCodeTemplate.EntityFileCodeParamters()
            {
                domainNamespace = this.DomainName,
                domainEntityName = entityName,
                domainBaseEntityName = _domainBaseEntityName,
            };
            //生成属性、引用属性
            parameters.normalProperties = this.RenderNormalProperties(table);
            parameters.refProperties = this.RenderRefProperties(table);
            parameters.tableConfig = entityName == table.Name ?
                "Meta.MapTable().MapAllProperties();" :
                string.Format(@"Meta.MapTable(""{0}"").MapAllProperties();", table.Name);
            parameters.columnConfig = this.RenderColumnConfig(table);

            //使用模板格式化字符串。
            var code = ItemCodeTemplate.GetEntityFileCode(parameters);

            //写到文件,并加入到项目中。
            var file = Path.Combine(Path.GetDirectoryName(_directory.get_FileNames(1)), fileName);
            File.WriteAllText(file, code);
            _directory.ProjectItems.AddFromFile(file);
            return true;
        }
예제 #13
0
 private IEnumerable<Column> FindIdentityColumns(Table table)
 {
     foreach (var column in table.Columns)
     {
         if (column.IsIdentity)
         {
             var columnNameLower = column.Name.ToLower();
             if (columnNameLower.EndsWith("id"))
             {
                 yield return column;
             }
         }
     }
 }
예제 #14
0
        private bool CheckHasPK(Table table)
        {
            //以下情况必须抛出异常,详情见:RenderNormalProperties 方法。
            var identites = FindIdentityColumns(table);
            var count = identites.Count();
            if (count != 1)
            {
                if (count == 0)
                {
                    AddError(string.Format("{0} 表中没有自增、命名以 Id 结尾的整形列。", table.Name));
                }
                else
                {
                    AddError(string.Format("{0} 表中自增长、命名并以 Id 结尾的整形列过多。", table.Name));
                }

                return false;
            }

            return true;
        }
예제 #15
0
 public void DMT_CreateTable()
 {
     this.Test(destination =>
     {
         var tmpTable = new Table("TestingTable", destination);
         tmpTable.AddColumn("Id", DbType.Int32, isPrimaryKey: true);
         tmpTable.AddColumn("Name", DbType.String);
         destination.Tables.Add(tmpTable);
     }, result =>
     {
         var tmpTable2 = result.FindTable("TestingTable");
         Assert.IsTrue(tmpTable2 != null);
         Assert.IsTrue(tmpTable2.Columns.Count == 2);
     });
 }
예제 #16
0
        /// <summary>
        /// 计算出新旧表之间的数据列差别
        /// </summary>
        /// <param name="oldTable">旧表</param>
        /// <param name="newTable">新表</param>
        /// <returns>
        /// 返回表之间区别,如果没有区别,则返回null
        /// </returns>
        private static TableChanges Distinguish(Table oldTable, Table newTable)
        {
            //if (newTable == null) throw new ArgumentNullException("newTable");
            //if (oldTable == null) throw new ArgumentNullException("oldTable");
            //if (newTable.Name != oldTable.Name) throw new InvalidOperationException("newTable.Name != oldTable.Name must be false.");

            var record = new TableChanges(oldTable, newTable, ChangeType.Modified);

            //先找到已经删除的列
            foreach (var oldColumn in oldTable.Columns)
            {
                if (newTable.FindColumn(oldColumn.Name) == null)
                {
                    record.ColumnsChanged.Add(new ColumnChanges(oldColumn, null, ChangeType.Removed));
                }
            }

            //记录新增的和更改过的列
            foreach (var column in newTable.Columns)
            {
                Column oldColumn = oldTable.FindColumn(column.Name);

                if (oldColumn == null)
                {
                    var columnChanged = new ColumnChanges(null, column, ChangeType.Added);
                    record.ColumnsChanged.Add(columnChanged);
                }
                else
                {
                    var columnChanged = Distinguish(oldColumn, column);
                    //新增的 或者 修改的 列
                    if (columnChanged != null) { record.ColumnsChanged.Add(columnChanged); }
                }
            }

            //如果被修改了,则返回record;否则返回null
            if (record.ColumnsChanged.Count > 0) { return record; }

            return null;
        }
예제 #17
0
        private string RenderNormalProperties(Table table)
        {
            var code = new StringBuilder();

            //先输出 Id 字段。
            var idColumn = RenderId(table);

            //Id 字段以外的其它字段,都可以输出了。
            foreach (var column in table.Columns)
            {
                if (!column.IsForeignKey && column != idColumn)
                {
                    string propertyType = string.Empty;
                    #region 转换到属性的类型

                    switch (column.DataType)
                    {
                        case DbType.AnsiString:
                        case DbType.AnsiStringFixedLength:
                        case DbType.StringFixedLength:
                        case DbType.Xml:
                        case DbType.String:
                            propertyType = "string";
                            break;
                        case DbType.Int16:
                        case DbType.Int32:
                        case DbType.Int64:
                        case DbType.SByte:
                        case DbType.UInt16:
                        case DbType.UInt32:
                        case DbType.UInt64:
                            propertyType = "int";
                            if (!column.IsRequired) propertyType += '?';
                            break;
                        case DbType.VarNumeric:
                        case DbType.Single:
                        case DbType.Double:
                            propertyType = "double";
                            if (!column.IsRequired) propertyType += '?';
                            break;
                        case DbType.Decimal:
                            propertyType = "decimal";
                            if (!column.IsRequired) propertyType += '?';
                            break;
                        case DbType.Date:
                        case DbType.DateTime:
                        case DbType.DateTime2:
                        case DbType.DateTimeOffset:
                        case DbType.Time:
                            propertyType = "DateTime";
                            if (!column.IsRequired) propertyType += '?';
                            break;
                        case DbType.Boolean:
                            propertyType = "bool";
                            if (!column.IsRequired) propertyType += '?';
                            break;
                        case DbType.Binary:
                            propertyType = "byte[]";
                            break;
                        case DbType.Byte:
                            propertyType = "byte";
                            break;
                        case DbType.Guid:
                            propertyType = "Guid";
                            if (!column.IsRequired) propertyType += '?';
                            break;
                        case DbType.Object:
                        case DbType.Currency:
                        default:
                            propertyType = "string";
                            break;
                    }

                    #endregion

                    var propertyCode = ItemCodeTemplate.GetNormalPropertyCode(ToEntityName(table), propertyType, column.Name);
                    code.Append(propertyCode);
                }
            }

            return code.ToString();
        }
예제 #18
0
        private string RenderRefProperties(Table table)
        {
            var code = new StringBuilder();

            foreach (var column in table.Columns)
            {
                if (column.IsForeignKey)
                {
                    //如果属性名以 Id 结尾,则直接去除 Id 即可。
                    //否则,映射失败,直接以列名作为引用属性的名称,添加列名 + Id 与属性名的映射。
                    string propertyName = string.Empty;
                    var columnName = column.Name;
                    if (columnName.ToLower().EndsWith("id"))
                    {
                        propertyName = columnName.Substring(0, columnName.Length - 2);
                    }
                    else
                    {
                        propertyName = columnName;
                    }

                    //处理一些类似于 RefEntity_Id 的字段,去掉最后的下划线。
                    while (propertyName[0] == '_') { propertyName = propertyName.Substring(1); }
                    while (propertyName[propertyName.Length - 1] == '_') { propertyName = propertyName.Substring(0, propertyName.Length - 1); }

                    //如果字段与属性名不同,需要添加属性的配置。
                    var idProperty = propertyName + "Id";
                    if (!idProperty.EqualsIgnoreCase(columnName))
                    {
                        _tablePropertiesConfig.Add(new PropertyConfig
                        {
                            PropertyName = idProperty,
                            ColumnName = columnName
                        });
                    }

                    var refEntity = ToEntityName(column.ForeignConstraint.PKTable);
                    var propertyCode = ItemCodeTemplate.GetRefPropertyCode(
                        ToEntityName(table), refEntity, propertyName,
                        isRequired: column.IsRequired
                        );
                    code.Append(propertyCode);
                }
            }

            return code.ToString();
        }
예제 #19
0
        private void AddTable(Table table)
        {
            var op = new CreateTable()
            {
                CopyFromTable = table
            };
            this.AddOperation(op);

            foreach (var column in table.FindNormalColumns())
            {
                this.AddColumn(column);
            }
        }