原理
通过反射实体所在程序集,得到枚举值列表,再通过sql获取数据库表结构,两者拼接成sql。
规范
实体枚举字段最好也加上Description特性,方便多次更新;
代码
实体定义
public partial class ProviderContract : Entity<int>
{
/// <summary>
/// 自增Id
/// </summary>
[Column("Id")]
public override int Id { get; set; }
/// <summary>
/// 供应商ID
/// </summary>
public int ProviderId { get; set; }
/// <summary>
/// 合同编号
/// </summary>
public string ContractNo { get; set; }
/// <summary>
/// 主营类目
/// </summary>
public ContractGoodsType GoodsType { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreatedTime { get; set; }
/// <summary>
/// 修改时间
/// </summary>
public DateTime? ModifiedTime { get; set; }
}
枚举定义
当读取不到枚举值的Description特性时,采用字段名称代替;
public enum ContractGoodsType
{
None = 0,
/// <summary>
/// 酒店
/// </summary>
Hotel = 1,
/// <summary>
/// 门票
/// </summary>
Ticket = 2,
/// <summary>
/// 市区娱乐
/// </summary>
UrbanEntertainment = 3,
/// <summary>
/// 实物
/// </summary>
MaterialObject = 7,
}
测试代码
public void Test()
{
var exceptTypeNames = new string[] { "AppId", "ApplicationId" };
var allEnumTypes = Assembly.Load("Core").GetTypes()
.Where(t => t.Namespace == "Core.Entities")
.SelectMany(r => r.GetProperties()
.Where(p => p.PropertyType.IsEnum && !p.CustomAttributes.Any() && !exceptTypeNames.Contains(p.Name)))
.Select(p => new
{
TableName = p.ReflectedType.Name,
ColumnName = p.Name,
EnumType = p.PropertyType
}).OrderBy(r => r.ColumnName).ToList();
List<TableDeclare> list;
using (var dapper = new DapperHelper())
{
var sql = @"select table_name, column_name, column_comment, column_type, column_default, is_nullable from information_schema.columns
where table_schema='test'";
list = dapper.Query<TableDeclare>(sql).ToList();
}
foreach (var item in allEnumTypes)
{
var enumDtos = item.EnumType.GetFields().Skip(1).Select(e => new
{
EnumValue = (int)e.GetValue(null),
EnumName = e.Name,
EnumDescAttr = e.GetCustomAttributes()
.Where(ac => ac.GetType() == typeof(DescriptionAttribute)).FirstOrDefault()
as DescriptionAttribute,
}).ToList();
var remark = string.Join(',',
enumDtos.Select(e => e.EnumValue + ":" + (e.EnumDescAttr == null ? e.EnumName : e.EnumDescAttr?.Description)));
var column = list.Where(l => l.table_name == item.TableName.ToLower() && l.column_name == item.ColumnName).FirstOrDefault();
//过滤原注释包含数字
if (column != null && !column.column_comment.Any(c => int.TryParse(c.ToString(), out int _)))
{
var nullable = column.is_nullable == "YES" ? " null " : string.Empty;
var defalutValue = column.column_default == null ? string.Empty : " default " + column.column_default + " ";
Debug.WriteLine($"ALTER TABLE `{column.table_name}` MODIFY COLUMN `{column.column_name}` {column.column_type}{nullable}{defalutValue} COMMENT '{column.column_comment}({remark})';");
}
}
}
private class TableDeclare
{
public string table_name { get; set; }
public string column_name { get; set; }
public string column_comment { get; set; }
public string column_type { get; set; }
public string column_default { get; set; }
public string is_nullable { get; set; }
}
生成的sql效果
ALTER TABLE `providercontract` MODIFY COLUMN `GoodsType` int(11) null default 0 COMMENT '主营类目(0:None,1:Hotel,2:Ticket,3:UrbanEntertainment,7:MaterialObject)'