/// <summary> /// 获取多对多的映射关系 /// </summary> /// <param name="entityContext"></param> /// <param name="joinTable"></param> private void CreateManyToMany(EntityContext entityContext, TableSchema joinTable) { if (joinTable.ForeignKeys.Count != 2) { return; } var joinTableName = joinTable.Name; var joinSchemaName = joinTable.Owner; // first fkey is always left, second fkey is right var leftForeignKey = joinTable.ForeignKeys[0]; var leftTable = leftForeignKey.PrimaryKeyTable; var joinLeftColumn = leftForeignKey.ForeignKeyMemberColumns.Select(c => c.Name).ToList(); var leftEntity = GetEntity(entityContext, leftTable, false, false); var rightForeignKey = joinTable.ForeignKeys[1]; var rightTable = rightForeignKey.PrimaryKeyTable; var joinRightColumn = rightForeignKey.ForeignKeyMemberColumns.Select(c => c.Name).ToList(); var rightEntity = GetEntity(entityContext, rightTable, false, false); string leftPropertyName = Settings.RelationshipName(rightEntity.ClassName); leftPropertyName = _namer.UniqueName(leftEntity.ClassName, leftPropertyName); string rightPropertyName = Settings.RelationshipName(leftEntity.ClassName); rightPropertyName = _namer.UniqueName(rightEntity.ClassName, rightPropertyName); string relationshipName = string.Format("{0}|{1}", leftForeignKey.Name, rightForeignKey.Name); relationshipName = _namer.UniqueRelationshipName(relationshipName); var left = new Relationship { RelationshipName = relationshipName, IsForeignKey = false, IsMapped = true, ThisCardinality = Cardinality.Many, ThisEntity = leftEntity.ClassName, ThisPropertyName = leftPropertyName, OtherCardinality = Cardinality.Many, OtherEntity = rightEntity.ClassName, OtherPropertyName = rightPropertyName, JoinTable = joinTableName, JoinSchema = joinSchemaName, JoinThisColumn = new List <string>(joinLeftColumn), JoinOtherColumn = new List <string>(joinRightColumn) }; leftEntity.Relationships.Add(left); var right = new Relationship { RelationshipName = relationshipName, IsForeignKey = false, IsMapped = false, ThisCardinality = Cardinality.Many, ThisEntity = rightEntity.ClassName, ThisPropertyName = rightPropertyName, OtherCardinality = Cardinality.Many, OtherEntity = leftEntity.ClassName, OtherPropertyName = leftPropertyName, JoinTable = joinTableName, JoinSchema = joinSchemaName, JoinThisColumn = new List <string>(joinRightColumn), JoinOtherColumn = new List <string>(joinLeftColumn) }; rightEntity.Relationships.Add(right); }
/// <summary> /// 创建数据库关系对应EF的Mapper /// </summary> /// <param name="entityContext">数据库上下文</param> /// <param name="foreignEntity">外键表对应实体</param> /// <param name="tableKeySchema">主键表</param> private void CreateRelationship(EntityContext entityContext, Entity foreignEntity, TableKeySchema tableKeySchema) { //获取主键表对应实体 Entity primaryEntity = GetEntity(entityContext, tableKeySchema.PrimaryKeyTable, false, false); //主表类名 string primaryName = primaryEntity.ClassName; //外键表名 string foreignName = foreignEntity.ClassName; //映射名称 string relationshipName = tableKeySchema.Name; //获取唯一映射名称 relationshipName = _namer.UniqueRelationshipName(relationshipName); //判断是否级联删除 bool isCascadeDelete = IsCascadeDelete(tableKeySchema); bool foreignMembersRequired; bool primaryMembersRequired; //获取外键表所有键属性名称 List <string> foreignMembers = GetKeyMembers(foreignEntity, tableKeySchema.ForeignKeyMemberColumns, tableKeySchema.Name, out foreignMembersRequired); //获取主表中所有键的成员属性名称 List <string> primaryMembers = GetKeyMembers(primaryEntity, tableKeySchema.PrimaryKeyMemberColumns, tableKeySchema.Name, out primaryMembersRequired); // 过滤没有外键主键的表处理 if (foreignMembers == null || primaryMembers == null) { return; } Relationship foreignRelationship = foreignEntity.Relationships .FirstOrDefault(r => r.RelationshipName == relationshipName && r.IsForeignKey); if (foreignRelationship == null) { foreignRelationship = new Relationship { RelationshipName = relationshipName }; foreignEntity.Relationships.Add(foreignRelationship); } foreignRelationship.IsMapped = true; foreignRelationship.IsForeignKey = true; foreignRelationship.ThisCardinality = foreignMembersRequired ? Cardinality.One : Cardinality.ZeroOrOne; foreignRelationship.ThisEntity = foreignName; foreignRelationship.ThisProperties = new List <string>(foreignMembers); foreignRelationship.OtherEntity = primaryName; foreignRelationship.OtherProperties = new List <string>(primaryMembers); foreignRelationship.CascadeDelete = isCascadeDelete; string prefix = GetMemberPrefix(foreignRelationship, primaryName, foreignName); string foreignPropertyName = ToPropertyName(foreignEntity.ClassName, prefix + primaryName); foreignPropertyName = _namer.UniqueName(foreignEntity.ClassName, foreignPropertyName); foreignRelationship.ThisPropertyName = foreignPropertyName; // add reverse Relationship primaryRelationship = primaryEntity.Relationships .FirstOrDefault(r => r.RelationshipName == relationshipName && r.IsForeignKey == false); if (primaryRelationship == null) { primaryRelationship = new Relationship { RelationshipName = relationshipName }; primaryEntity.Relationships.Add(primaryRelationship); } primaryRelationship.IsMapped = false; primaryRelationship.IsForeignKey = false; primaryRelationship.ThisEntity = primaryName; primaryRelationship.ThisProperties = new List <string>(primaryMembers); primaryRelationship.OtherEntity = foreignName; primaryRelationship.OtherProperties = new List <string>(foreignMembers); primaryRelationship.CascadeDelete = isCascadeDelete; bool isOneToOne = IsOneToOne(tableKeySchema, foreignRelationship); if (isOneToOne) { primaryRelationship.ThisCardinality = primaryMembersRequired ? Cardinality.One : Cardinality.ZeroOrOne; } else { primaryRelationship.ThisCardinality = Cardinality.Many; } string primaryPropertyName = prefix + foreignName; if (!isOneToOne) { primaryPropertyName = Settings.RelationshipName(primaryPropertyName); } primaryPropertyName = ToPropertyName(primaryEntity.ClassName, primaryPropertyName); primaryPropertyName = _namer.UniqueName(primaryEntity.ClassName, primaryPropertyName); primaryRelationship.ThisPropertyName = primaryPropertyName; foreignRelationship.OtherPropertyName = primaryRelationship.ThisPropertyName; foreignRelationship.OtherCardinality = primaryRelationship.ThisCardinality; primaryRelationship.OtherPropertyName = foreignRelationship.ThisPropertyName; primaryRelationship.OtherCardinality = foreignRelationship.ThisCardinality; foreignRelationship.IsProcessed = true; primaryRelationship.IsProcessed = true; }
/// <summary> /// 创建数据库关系对应EF的Mapper /// </summary> /// <param name="entityContext">数据库上下文</param> /// <param name="foreignEntity">外键表对应实体</param> /// <param name="tableKeySchema">主键表</param> private void CreateRelationship(EntityContext entityContext, Entity foreignEntity, TableKeySchema tableKeySchema) { //获取主键表对应实体 Entity primaryEntity = GetEntity(entityContext, tableKeySchema.PrimaryKeyTable, false, false); //主表类名 string primaryName = primaryEntity.ClassName; //外键表名 string foreignName = foreignEntity.ClassName; //映射名称 string relationshipName = tableKeySchema.Name; //获取唯一映射名称 relationshipName = _namer.UniqueRelationshipName(relationshipName); //判断是否级联删除 bool isCascadeDelete = IsCascadeDelete(tableKeySchema); bool foreignMembersRequired; bool primaryMembersRequired; //获取外键表所有键属性名称 List<string> foreignMembers = GetKeyMembers(foreignEntity, tableKeySchema.ForeignKeyMemberColumns, tableKeySchema.Name, out foreignMembersRequired); //获取主表中所有键的成员属性名称 List<string> primaryMembers = GetKeyMembers(primaryEntity, tableKeySchema.PrimaryKeyMemberColumns, tableKeySchema.Name, out primaryMembersRequired); // 过滤没有外键主键的表处理 if (foreignMembers == null || primaryMembers == null) return; Relationship foreignRelationship = foreignEntity.Relationships .FirstOrDefault(r => r.RelationshipName == relationshipName && r.IsForeignKey); if (foreignRelationship == null) { foreignRelationship = new Relationship { RelationshipName = relationshipName }; foreignEntity.Relationships.Add(foreignRelationship); } foreignRelationship.IsMapped = true; foreignRelationship.IsForeignKey = true; foreignRelationship.ThisCardinality = foreignMembersRequired ? Cardinality.One : Cardinality.ZeroOrOne; foreignRelationship.ThisEntity = foreignName; foreignRelationship.ThisProperties = new List<string>(foreignMembers); foreignRelationship.OtherEntity = primaryName; foreignRelationship.OtherProperties = new List<string>(primaryMembers); foreignRelationship.CascadeDelete = isCascadeDelete; string prefix = GetMemberPrefix(foreignRelationship, primaryName, foreignName); string foreignPropertyName = ToPropertyName(foreignEntity.ClassName, prefix + primaryName); foreignPropertyName = _namer.UniqueName(foreignEntity.ClassName, foreignPropertyName); foreignRelationship.ThisPropertyName = foreignPropertyName; // add reverse Relationship primaryRelationship = primaryEntity.Relationships .FirstOrDefault(r => r.RelationshipName == relationshipName && r.IsForeignKey == false); if (primaryRelationship == null) { primaryRelationship = new Relationship { RelationshipName = relationshipName }; primaryEntity.Relationships.Add(primaryRelationship); } primaryRelationship.IsMapped = false; primaryRelationship.IsForeignKey = false; primaryRelationship.ThisEntity = primaryName; primaryRelationship.ThisProperties = new List<string>(primaryMembers); primaryRelationship.OtherEntity = foreignName; primaryRelationship.OtherProperties = new List<string>(foreignMembers); primaryRelationship.CascadeDelete = isCascadeDelete; bool isOneToOne = IsOneToOne(tableKeySchema, foreignRelationship); if (isOneToOne) primaryRelationship.ThisCardinality = primaryMembersRequired ? Cardinality.One : Cardinality.ZeroOrOne; else primaryRelationship.ThisCardinality = Cardinality.Many; string primaryPropertyName = prefix + foreignName; if (!isOneToOne) primaryPropertyName = Settings.RelationshipName(primaryPropertyName); primaryPropertyName = ToPropertyName(primaryEntity.ClassName, primaryPropertyName); primaryPropertyName = _namer.UniqueName(primaryEntity.ClassName, primaryPropertyName); primaryRelationship.ThisPropertyName = primaryPropertyName; foreignRelationship.OtherPropertyName = primaryRelationship.ThisPropertyName; foreignRelationship.OtherCardinality = primaryRelationship.ThisCardinality; primaryRelationship.OtherPropertyName = foreignRelationship.ThisPropertyName; primaryRelationship.OtherCardinality = foreignRelationship.ThisCardinality; foreignRelationship.IsProcessed = true; primaryRelationship.IsProcessed = true; }
/// <summary> /// 获取多对多的映射关系 /// </summary> /// <param name="entityContext"></param> /// <param name="joinTable"></param> private void CreateManyToMany(EntityContext entityContext, TableSchema joinTable) { if (joinTable.ForeignKeys.Count != 2) return; var joinTableName = joinTable.Name; var joinSchemaName = joinTable.Owner; // first fkey is always left, second fkey is right var leftForeignKey = joinTable.ForeignKeys[0]; var leftTable = leftForeignKey.PrimaryKeyTable; var joinLeftColumn = leftForeignKey.ForeignKeyMemberColumns.Select(c => c.Name).ToList(); var leftEntity = GetEntity(entityContext, leftTable, false, false); var rightForeignKey = joinTable.ForeignKeys[1]; var rightTable = rightForeignKey.PrimaryKeyTable; var joinRightColumn = rightForeignKey.ForeignKeyMemberColumns.Select(c => c.Name).ToList(); var rightEntity = GetEntity(entityContext, rightTable, false, false); string leftPropertyName = Settings.RelationshipName(rightEntity.ClassName); leftPropertyName = _namer.UniqueName(leftEntity.ClassName, leftPropertyName); string rightPropertyName = Settings.RelationshipName(leftEntity.ClassName); rightPropertyName = _namer.UniqueName(rightEntity.ClassName, rightPropertyName); string relationshipName = string.Format("{0}|{1}", leftForeignKey.Name, rightForeignKey.Name); relationshipName = _namer.UniqueRelationshipName(relationshipName); var left = new Relationship { RelationshipName = relationshipName, IsForeignKey = false, IsMapped = true, ThisCardinality = Cardinality.Many, ThisEntity = leftEntity.ClassName, ThisPropertyName = leftPropertyName, OtherCardinality = Cardinality.Many, OtherEntity = rightEntity.ClassName, OtherPropertyName = rightPropertyName, JoinTable = joinTableName, JoinSchema = joinSchemaName, JoinThisColumn = new List<string>(joinLeftColumn), JoinOtherColumn = new List<string>(joinRightColumn) }; leftEntity.Relationships.Add(left); var right = new Relationship { RelationshipName = relationshipName, IsForeignKey = false, IsMapped = false, ThisCardinality = Cardinality.Many, ThisEntity = rightEntity.ClassName, ThisPropertyName = rightPropertyName, OtherCardinality = Cardinality.Many, OtherEntity = leftEntity.ClassName, OtherPropertyName = leftPropertyName, JoinTable = joinTableName, JoinSchema = joinSchemaName, JoinThisColumn = new List<string>(joinRightColumn), JoinOtherColumn = new List<string>(joinLeftColumn) }; rightEntity.Relationships.Add(right); }
/// <summary> /// 判断一对一的关系 /// </summary> /// <param name="tableKeySchema"></param> /// <param name="foreignRelationship"></param> /// <returns></returns> private static bool IsOneToOne(TableKeySchema tableKeySchema, Relationship foreignRelationship) { bool isFkeyPkey = tableKeySchema.ForeignKeyTable.HasPrimaryKey && tableKeySchema.ForeignKeyTable.PrimaryKey != null && tableKeySchema.ForeignKeyTable.PrimaryKey.MemberColumns.Count == 1 && tableKeySchema.ForeignKeyTable.PrimaryKey.MemberColumns.Contains( foreignRelationship.ThisProperties.FirstOrDefault()); if (isFkeyPkey) return true; return false; // if f.key is unique //return tableKeySchema.ForeignKeyMemberColumns.All(column => column.IsUnique); }
private static string GetMemberPrefix(Relationship relationship, string primaryClass, string foreignClass) { string thisKey = relationship.ThisProperties.FirstOrDefault() ?? string.Empty; string otherKey = relationship.OtherProperties.FirstOrDefault() ?? string.Empty; bool isSameName = thisKey.Equals(otherKey, StringComparison.OrdinalIgnoreCase); isSameName = (isSameName || thisKey.Equals(primaryClass + otherKey, StringComparison.OrdinalIgnoreCase)); string prefix = string.Empty; if (isSameName) return prefix; prefix = thisKey.Replace(otherKey, ""); prefix = prefix.Replace(primaryClass, ""); prefix = prefix.Replace(foreignClass, ""); prefix = Regex.Replace(prefix, @"(_ID|_id|_Id|\.ID|\.id|\.Id|ID|Id)$", ""); prefix = Regex.Replace(prefix, @"^\d", ""); return prefix; }