using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data; using System.Diagnostics; using System.Linq; using System.Text; using System.Xml.Serialization; using CodeSmith.Core.Extensions; namespace SchemaMapper { /// /// 系统操作 /// public class Sys { /// /// 调试 /// public static void Debug() { System.Diagnostics.Debugger.Launch(); System.Diagnostics.Debugger.Break(); } } /// /// 扩展 - 可空类型 /// public static class NullExtensions { /// /// 安全返回值 /// /// 可空值 public static T SafeValue(this T? value) where T : struct { return value ?? default(T); } } #region Base public enum Cardinality { ZeroOrOne, One, Many } public class EntityBase { public bool IsProcessed { get; set; } } #endregion #region Model [DebuggerDisplay("Context: {ContextName}, Database: {DatabaseName}")] public class EntityContext : EntityBase { public EntityContext() { Entities = new EntityCollection(); } public string ClassName { get; set; } public string DatabaseName { get; set; } public EntityCollection Entities { get; set; } public void RenameEntity(string originalName, string newName) { if (originalName == newName) return; Debug.WriteLine("Rename Entity '{0}' to '{1}'.", originalName, newName); foreach (var entity in Entities) { if (entity.ClassName == originalName) entity.ClassName = newName; foreach (var relationship in entity.Relationships) { if (relationship.ThisEntity == originalName) relationship.ThisEntity = newName; if (relationship.OtherEntity == originalName) relationship.OtherEntity = newName; } } } public void RenameProperty(string entityName, string originalName, string newName) { if (originalName == newName) return; Debug.WriteLine("Rename Property '{0}' to '{1}' in Entity '{2}'.", originalName, newName, entityName); foreach (var entity in Entities) { if (entity.ClassName == entityName) { var property = entity.Properties.ByProperty(originalName); if (property != null) property.PropertyName = newName; } foreach (var relationship in entity.Relationships) { if (relationship.ThisEntity == entityName) for (int i = 0; i < relationship.ThisProperties.Count; i++) if (relationship.ThisProperties[i] == originalName) relationship.ThisProperties[i] = newName; if (relationship.OtherEntity == entityName) for (int i = 0; i < relationship.OtherProperties.Count; i++) if (relationship.OtherProperties[i] == originalName) relationship.OtherProperties[i] = newName; } } } } [DebuggerDisplay("Class: {ClassName}, Table: {FullName}, Context: {ContextName}")] public class Entity : EntityBase { public Entity() { Properties = new PropertyCollection(); Relationships = new RelationshipCollection(); Methods = new MethodCollection(); } public EntityContext Context { get; set; } public string ContextName { get; set; } public string ClassName { get; set; } public string MappingName { get; set; } public string TableSchema { get; set; } public string TableName { get; set; } public string FullName { get; set; } /// /// 描述 /// public string Description { get; set; } public PropertyCollection Properties { get; set; } public RelationshipCollection Relationships { get; set; } public MethodCollection Methods { get; set; } /// /// 获取主键 /// public Property GetId() { foreach (var property in Properties) { if (property.IsPrimaryKey.SafeValue()) return property; } return new Property(); } /// /// 获取导航属性描述 /// public string GetOtherDescription(string name) { return Context.Entities.ByClass(name).Description; } /// /// 获取导航属性标识列名 /// public string GetOtherIdProperty(string name) { return Context.Entities.ByClass(name).GetId().ColumnName; } /// /// 获取属性集合,不包含Version属性 /// public List GetProperties(bool isExcludeVersion = true) { if (isExcludeVersion) return Properties.Where(t => (t.ColumnName == "Version" && t.DataType == DbType.Binary) == false).ToList(); return Properties.ToList(); } /// /// 获取第一个不是Id的属性 /// public Property GetFirstProperty() { return GetProperties().FirstOrDefault(t => t.IsPrimaryKey != true) ?? new Property(); } /// /// 是否最后一个属性 /// public bool IsLast(Property property, bool isExcludeVersion = true) { return GetProperties(isExcludeVersion).Last() == property; } /// /// 获取逗号 /// /// 属性 /// 是否排除版本号 public string GetComma(Property property, bool isExcludeVersion = true) { return IsLast(property, isExcludeVersion) ? "" : ","; } /// /// 获取主键 /// public Property GetKey() { var key = Properties.FirstOrDefault(t => t.IsPrimaryKey.SafeValue()); if (key == null) throw new Exception("没有设置主键"); return key; } /// /// 获取主键类型 /// public Type GetKeyType() { var key = GetKey(); return key.SystemType; } /// /// 获取主键类型 /// public string GetKeyTypeString() { return GetKeyType().ToNullableType(); } /// /// 获取聚合根 /// public string GetAggregateRoot() { if (GetKeyType() == typeof(string)) return string.Format("AggregateRoot<{0},string>", ClassName); if (GetKeyType() == typeof(int)) return string.Format("AggregateRoot<{0},int>", ClassName); if (GetKeyType() == typeof(long)) return string.Format("AggregateRoot<{0},long>", ClassName); return string.Format("AggregateRoot<{0}>", ClassName); } /// /// 获取树型实体和需要实现的接口 /// public string GetTreeEntityAndInterfaces() { StringBuilder result = new StringBuilder(); result.Append(GetTreeEntity()); result.Append(GetInterfaces()); return result.ToString(); } /// /// 获取聚合根 /// public string GetTreeEntity() { if (GetKeyType() == typeof(string)) return string.Format("TreeEntityBase<{0},string,string>", ClassName); if (GetKeyType() == typeof(int)) return string.Format("TreeEntityBase<{0},int,int?>", ClassName); return string.Format("TreeEntityBase<{0}>", ClassName); } /// /// 获取聚合根和需要实现的接口 /// public string GetAggregateRootAndInterfaces() { StringBuilder result = new StringBuilder(); result.Append(GetAggregateRoot()); result.Append(GetInterfaces()); return result.ToString(); } /// /// 获取需要实现的接口 /// public string GetInterfaces() { StringBuilder result = new StringBuilder(); result.Append(GetITenant()); result.Append(GetISoftDelete()); result.Append(GetIAudited()); return result.ToString(); } /// /// 获取租户接口 /// private string GetITenant() { if (Properties.Any(t => t.ColumnName == "TenantId")) return ",ITenant"; return string.Empty; } /// /// 获取逻辑删除接口 /// private string GetISoftDelete() { if (Properties.Any(t => t.ColumnName == "IsDeleted")) return ",IDelete"; return string.Empty; } /// /// 获取审计接口 /// private string GetIAudited() { if (IsCreationAudited() && IsModificationAudited() ) return ",IAudited"; if (IsCreationAudited()) return ",ICreationAudited"; if (IsModificationAudited()) return ",IModificationAudited"; return string.Empty; } /// /// 是否创建审计 /// private bool IsCreationAudited() { return Properties.Any( t => t.ColumnName == "CreationTime" )&&Properties.Any( t => t.ColumnName == "CreatorId" ); } /// /// 是否修改审计 /// private bool IsModificationAudited() { return Properties.Any(t => t.ColumnName == "LastModificationTime") && Properties.Any(t => t.ColumnName == "LastModifierId"); } /// /// 获取主键默认值 /// public string GetKeyDefault() { if (GetKeyType() == typeof(string)) return "string.Empty"; if (GetKeyType() == typeof(int)) return "0"; if (GetKeyType() == typeof(long)) return "0"; return "Guid.Empty"; } /// /// 获取键类型,但不包括Guid /// /// 是否在前面添加逗号 public string GetKeyTypeNoContainsGuid(bool isAddCommon = true) { if (GetKeyType() == typeof(Guid)) return ""; string comma = isAddCommon ? "," : ""; return comma + GetKeyTypeString(); } /// /// 获取转换为实体 /// public string GetToEntityConvert() { if (GetKeyType() == typeof(Guid)) return ".ToGuid()"; if (GetKeyType() == typeof(int)) return ".ToInt()"; return ""; } /// /// 获取转换为Dto /// public string GetToDtoConvert() { if (GetKeyType() == typeof(Guid)) return ".ToString()"; return ""; } /// /// 获取新的主键值 /// public string GetNewKey() { if (GetKeyType() == typeof(Guid)) return "Guid.NewGuid()"; if (GetKeyType() == typeof(string)) return "Guid.NewGuid().ToString()"; return ""; } /// /// 获取排序字段 /// public string GetOrderBy() { var exists = Properties.Any(t => t.PropertyName == "CreationTime" && t.SystemType == typeof(DateTime)); if (exists) return "CreationTime"; return "Id"; } /// /// 获取名称空间 /// /// 基名称空间 /// 层 /// 分类 public string GetNamespace(string baseNamespace, string layer, string category = "") { if (string.IsNullOrWhiteSpace(TableSchema) || TableSchema.ToLower().Trim() == "dbo") return string.Format("{0}.{1}{2}", baseNamespace, layer, GetCategory(category)); return string.Format("{0}.{1}.{2}{3}", baseNamespace, TableSchema, layer, GetCategory(category)); } /// /// 获取分类 /// private string GetCategory(string category) { if (string.IsNullOrWhiteSpace(category)) return string.Empty; return string.Format(".{0}", category); } /// /// 查询实体属性过滤 /// /// 属性 public bool IsFilterByQueryObject(Property property) { if (property.ColumnName == "Version" && property.DataType == DbType.Binary) return true; if (property.ColumnName == "IsDeleted" && property.DataType == DbType.Boolean) return true; return false; } /// /// 是否隐藏 /// /// 属性 public bool IsHidden(Property property) { if (property.ColumnName == "Version" && property.DataType == DbType.Binary) return true; if (property.ColumnName == "IsDeleted" && property.DataType == DbType.Boolean) return true; if (property.ColumnName == "CreationTime" && property.DataType == DbType.DateTime) return true; if (property.ColumnName == "CreatorId" && property.DataType == DbType.Guid) return true; if (property.ColumnName == "LastModificationTime" && property.DataType == DbType.DateTime) return true; if (property.ColumnName == "LastModifierId" && property.DataType == DbType.Guid ) return true; return false; } /// /// 是否在详情隐藏 /// /// 属性 public bool IsDetailHidden(Property property) { if (property.ColumnName == "Version" && property.DataType == DbType.Binary) return true; if (property.ColumnName == "IsDeleted" && property.DataType == DbType.Boolean) return true; if (property.ColumnName == "CreatorId" && property.DataType == DbType.Guid) return true; if (property.ColumnName == "LastModificationTime" && property.DataType == DbType.DateTime) return true; if (property.ColumnName == "LastModifierId" && property.DataType == DbType.Guid) return true; return false; } /// /// 获取格式化 /// /// 属性 public string GetFormat(Property property) { if (property.DataType == DbType.Boolean) return ".Description()"; if (property.DataType == DbType.DateTime) return ".ToDateTimeString( true )"; return string.Empty; } /// /// 获取Grid显示的属性集合 /// public List GetGridProperties() { return Properties.Where(t => ( t.ColumnName == "Version" && t.DataType == DbType.Binary ) == false && ( t.ColumnName == "IsDeleted" && t.DataType == DbType.Boolean ) == false && ( t.ColumnName == "CreatorId" && t.DataType == DbType.Guid ) == false && ( t.ColumnName == "LastModificationTime" && t.DataType == DbType.DateTime ) == false && (t.ColumnName == "LastModifierId" && t.DataType == DbType.Guid) == false && (t.ColumnName == "TenantId" && t.DataType == DbType.String) == false ) .ToList(); } /// /// 获取Grid项的逗号 /// /// 属性 public string GetGridComma(Property property) { return GetGridProperties().Last() == property ? "" : ","; } /// /// 是否树型实体 /// public bool IsTreeEntity() { if (Properties.Any(t => t.ColumnName == "ParentId") && Properties.Any(t => t.ColumnName == "Path") && Properties.Any(t => t.ColumnName == "Level")) { return true; } return false; } /// /// 忽略树型实体属性 /// public bool IgnoreTreeEntityProperty(Property property) { if (property.ColumnName == "ParentId") return true; if (property.ColumnName == "Path" && property.DataType == DbType.String) return true; if (property.ColumnName == "Level" && property.DataType == DbType.Int32) return true; if (property.ColumnName == "Enabled" && property.DataType == DbType.Boolean) return true; if (property.ColumnName == "SortId" && property.DataType == DbType.Int32) return true; return false; } } [DebuggerDisplay("Property: {PropertyName}, Column: {ColumnName}, Type: {NativeType}")] public class Property : EntityBase { /// /// 属性名 /// public string PropertyName { get; set; } /// /// 列名 /// public string ColumnName { get; set; } /// /// 描述 /// public string Description { get; set; } public DbType DataType { get; set; } public string NativeType { get; set; } [XmlIgnore] public Type SystemType { get; set; } public int? Order { get; set; } public bool OrderSpecified { get { return Order.HasValue; } } public bool? IsNullable { get; set; } public bool IsNullableSpecified { get { return IsNullable.HasValue; } } public bool IsRequired { get { return IsNullable == false; } set { IsNullable = !value; } } public bool IsOptional { get { return IsNullable == true; } set { IsNullable = value; } } public bool? IsPrimaryKey { get; set; } public bool IsPrimaryKeySpecified { get { return IsPrimaryKey.HasValue; } } public bool? IsForeignKey { get; set; } public bool IsForeignKeySpecified { get { return IsForeignKey.HasValue; } } public bool? IsAutoGenerated { get; set; } public bool IsAutoGeneratedSpecified { get { return IsAutoGenerated.HasValue; } } public bool? IsReadOnly { get; set; } public bool IsReadOnlySpecified { get { return IsReadOnly.HasValue; } } public bool? IsRowVersion { get; set; } public bool IsRowVersionSpecified { get { return IsRowVersion.HasValue; } } public bool? IsIdentity { get; set; } public bool IsIdentitySpecified { get { return IsIdentity.HasValue; } } public bool? IsUnique { get; set; } public bool IsUniqueSpecified { get { return IsUnique.HasValue; } } public bool? IsUnicode { get; set; } public bool IsUnicodeSpecified { get { return IsUnicode.HasValue; } } public bool? IsFixedLength { get; set; } public bool IsFixedLengthSpecified { get { return IsFixedLength.HasValue; } } public int? MaxLength { get; set; } public bool MaxLengthSpecified { get { return MaxLength.HasValue; } } public byte? Precision { get; set; } public bool PrecisionSpecified { get { return Precision.HasValue; } } public int? Scale { get; set; } public bool ScaleSpecified { get { return Scale.HasValue; } } /// /// 是否需要验证 /// public bool HasValidate() { var result = GetValidations(); if (result.Count > 0) return true; return false; } /// /// 获取验证列表 /// private List GetValidations() { List result = new List(); ValidateRequired(result); ValidateStringLength(result); return result; } /// /// 验证是否必填项 /// private void ValidateRequired(List result) { if (IsRequired == false) return; if (DataType == DbType.Boolean) return; result.Add(string.Format("[Required(ErrorMessage = \"{0}不能为空\")]", Description)); } /// /// 验证字符串长度 /// private void ValidateStringLength(List result) { if (SystemType != typeof(String)) return; if (MaxLength == -1) return; result.Add(string.Format("[StringLength( {0} )]", MaxLength, Description)); } /// /// 验证 /// public string Validate() { StringBuilder result = new StringBuilder(); List validations = GetValidations(); if (validations.Count == 1) result.Append(validations[0]); else AddValidations(result, validations); return result.ToString(); } /// /// 添加验证列表 /// private void AddValidations(StringBuilder result, List validations) { for (int i = 0; i < validations.Count; i++) { if (i == 0) { result.AppendFormat("{0}\r\n", validations[i]); continue; } if (i == validations.Count - 1) result.AppendFormat(" {0}", validations[i]); else { result.AppendFormat(" {0}\r\n", validations[i]); } } } /// /// 设置Description方法 /// public string ShowDescription() { if (DataType == DbType.Boolean) return ".Description()"; return string.Empty; } /// /// 类型名称 /// public string TypeName { get { return SystemType.ToNullableType(IsNullable == true); } } /// /// 是否标识 /// public bool IsKey { get { return IsPrimaryKey.SafeValue(); } } /// /// 格式化表格列 /// public string FormatGridColumn() { if (SystemType == typeof(DateTime)) return ".FormatDate()"; if (SystemType == typeof(bool)) return ".FormatBool()"; return string.Empty; } /// /// 获取表格列宽 /// public string GetGridColumnWidth() { if (SystemType == typeof(DateTime)) return "120"; if (SystemType == typeof(bool)) return "60"; return "100"; } /// /// 获取显示名称 /// public string GetDisplayName() { if (!string.IsNullOrWhiteSpace(Description)) return Description; return PropertyName; } } [DebuggerDisplay("Other: {OtherEntity}, Property: {OtherPropertyName}, Relationship: {RelationshipName}")] public class Relationship : EntityBase { public Relationship() { OtherProperties = new List(); ThisProperties = new List(); } public string RelationshipName { get; set; } public string ThisEntity { get; set; } public string ThisPropertyName { get; set; } public Cardinality ThisCardinality { get; set; } public List ThisProperties { get; set; } public string OtherEntity { get; set; } public string OtherPropertyName { get; set; } public Cardinality OtherCardinality { get; set; } public List OtherProperties { get; set; } public bool? DeleteOnNull { get; set; } public bool IsForeignKey { get; set; } public bool IsMapped { get; set; } public bool IsManyToMany { get { return ThisCardinality == Cardinality.Many && OtherCardinality == Cardinality.Many; } } public bool IsOneToOne { get { return ThisCardinality != Cardinality.Many && OtherCardinality != Cardinality.Many; } } public string JoinTable { get; set; } public string JoinSchema { get; set; } public List JoinThisColumn { get; set; } public List JoinOtherColumn { get; set; } } [DebuggerDisplay("Suffix: {NameSuffix}, IsKey: {IsKey}, IsUnique: {IsUnique}")] public class Method : EntityBase { public Method() { Properties = new List(); } public string NameSuffix { get; set; } public string SourceName { get; set; } public bool IsKey { get; set; } public bool IsUnique { get; set; } public bool IsIndex { get; set; } public List Properties { get; set; } } #endregion #region Collections public class EntityCollection : ObservableCollection { public bool IsProcessed { get; set; } public Entity ByTable(string fullName) { return this.FirstOrDefault(x => x.FullName == fullName); } public Entity ByTable(string tableName, string tableSchema) { return this.FirstOrDefault(x => x.TableName == tableName && x.TableSchema == tableSchema); } public Entity ByClass(string className) { return this.FirstOrDefault(x => x.ClassName == className); } public Entity ByContext(string contextName) { return this.FirstOrDefault(x => x.ContextName == contextName); } } public class PropertyCollection : ObservableCollection { public bool IsProcessed { get; set; } public IEnumerable PrimaryKeys { get { return this.Where(p => p.IsPrimaryKey == true); } } public IEnumerable ForeignKeys { get { return this.Where(p => p.IsForeignKey == true); } } public Property ByColumn(string columnName) { return this.FirstOrDefault(x => x.ColumnName == columnName); } public Property ByProperty(string propertyName) { return this.FirstOrDefault(x => x.PropertyName == propertyName); } } public class RelationshipCollection : ObservableCollection { public bool IsProcessed { get; set; } public Relationship ByName(string name) { return this.FirstOrDefault(x => x.RelationshipName == name); } public Relationship ByProperty(string propertyName) { return this.FirstOrDefault(x => x.ThisPropertyName == propertyName); } public Relationship ByOther(string name) { return this.FirstOrDefault(x => x.OtherEntity == name); } } public class MethodCollection : ObservableCollection { public bool IsProcessed { get; set; } } #endregion }