/// <summary> /// 根据数据库结构获取实体上下文对象 /// </summary> /// <param name="databaseSchema">数据库结构</param> /// <returns></returns> public EntityContext Generate(SchemaSelector databaseSchema) { EntityContext entityContext = new EntityContext { DatabaseName = databaseSchema.Database.Name }; string dataContextName = StringUtil.ToPascalCase(entityContext.DatabaseName) + "Context"; dataContextName = _namer.UniqueClassName(dataContextName); entityContext.ClassName = dataContextName; var tables = databaseSchema.Tables .Selected() .OrderBy(t => t.SortName) .ToTables(); foreach (TableSchema t in tables) { if (IsManyToMany(t)) { Debug.WriteLine("多对多表: " + t.FullName); CreateManyToMany(entityContext, t); } else { Debug.WriteLine("表: " + t.FullName); GetEntity(entityContext, t); } OnSchemaItemProcessed(t.FullName); } if (!Settings.IncludeViews) return entityContext; // 数据库视图生成EF实体 var views = databaseSchema.Views .Selected() .OrderBy(t => t.SortName) .ToViews(); foreach (ViewSchema v in views) { Debug.WriteLine("视图: " + v.FullName); GetEntity(entityContext, v); OnSchemaItemProcessed(v.FullName); } return entityContext; }
/// <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> /// 获取数据库视图对应实体对象 /// </summary> /// <param name="entityContext"></param> /// <param name="viewSchema"></param> /// <returns></returns> private void GetEntity(EntityContext entityContext, ViewSchema viewSchema) { string key = viewSchema.FullName; Entity entity = entityContext.Entities.ByTable(key) ?? CreateEntity(entityContext, viewSchema); if (!entity.Properties.IsProcessed) CreateProperties(entity, viewSchema.Columns); entity.IsProcessed = true; }
/// <summary> /// 获取数据库表对应实体对象 /// </summary> /// <param name="entityContext">数据库上下文处理对象</param> /// <param name="tableSchema">表结构对象</param> /// <param name="processRelationships">是否处理实体映射关系</param> /// <param name="processMethods">是否处理实体扩展查询方法</param> /// <returns></returns> private Entity GetEntity(EntityContext entityContext, TableSchema tableSchema, bool processRelationships = true, bool processMethods = true) { string key = tableSchema.FullName; Entity entity = entityContext.Entities.ByTable(key) ?? CreateEntity(entityContext, tableSchema); if (!entity.Properties.IsProcessed) CreateProperties(entity, tableSchema.Columns.Selected()); if (processRelationships && !entity.Relationships.IsProcessed) CreateRelationships(entityContext, entity, tableSchema); if (processMethods && !entity.Methods.IsProcessed) CreateMethods(entity, tableSchema); entity.IsProcessed = true; return entity; }
/// <summary> /// 获取数据库表中外键字段对应EF映射 /// </summary> /// <param name="entityContext"></param> /// <param name="entity"></param> /// <param name="tableSchema"></param> private void CreateRelationships(EntityContext entityContext, Entity entity, TableSchema tableSchema) { foreach (TableKeySchema tableKey in tableSchema.ForeignKeys.Selected()) { CreateRelationship(entityContext, entity, tableKey); } entity.Relationships.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="entityContext"></param> /// <param name="tableSchema"></param> /// <returns></returns> private Entity CreateEntity(EntityContext entityContext, TabularObjectBase tableSchema) { var entity = new Entity { FullName = tableSchema.FullName, TableName = tableSchema.Name, TableSchema = tableSchema.Owner }; string className = ToClassName(tableSchema.Name); className = _namer.UniqueClassName(className); string mappingName = className + "Map"; mappingName = _namer.UniqueClassName(mappingName); string contextName = Settings.ContextName(className); contextName = ToPropertyName(entityContext.ClassName, contextName); contextName = _namer.UniqueContextName(contextName); entity.ClassName = className; entity.ContextName = contextName; entity.MappingName = mappingName; entityContext.Entities.Add(entity); return entity; }