public void Generate(DatabaseDefinition databaseDefinition) { Log(LogSeverity.Information, "Starting on {DatabaseName}.", "BimGenerator", DatabaseName); var root = new BimGeneratorRoot { Model = new BimGeneratorModel() }; BimHelper.SetDefaultAnnotations(root.Model); BimHelper.SetDefaultDataSources(root.Model, DatabaseName); var relationShipRegistrations = new RelationShipRegistrations(); foreach (var sqlTable in databaseDefinition.GetTables()) { if (!Context.Customizer.ShouldSkip(sqlTable.SchemaAndTableName) && !DocumenterWriterBase.ShouldSkipKnownTechnicalTable(sqlTable.SchemaAndTableName) ) { root.Model.Tables.Add(GenerateTable(sqlTable)); Context.Logger.Log(LogSeverity.Debug, "Table {TableName} added to bim model.", "BimGenerator", sqlTable.SchemaAndTableName); GatherReferencedTablesByFK(relationShipRegistrations, sqlTable); } } GenerateReferences(relationShipRegistrations, root.Model); var jsonString = ToJson(root); jsonString = RemoveInvalidEmptyItems(jsonString); WriteJson(jsonString); }
private void GenerateReferences(RelationShipRegistrations relationShipRegistrations, BimGeneratorModel model) { // Create shadow copies where multiple FKs are on a source table // Use same RelationShipIdentifier // Omit Source table if no other FK is pointing to it foreach (var fromTable in relationShipRegistrations.FromTables()) { var toTables = new Dictionary <string, int>(); var to = relationShipRegistrations.GetByFromTable(fromTable); foreach (var rr in to) { if (rr.FromTableSchemaAndTableName == rr.ToTableSchemaAndTableName) { Context.Logger.Log(LogSeverity.Warning, "Table {TableName} is referencing itself. SKIPPED.", "BimGenerator", fromTable); continue; } var trp = rr.FromColumn.Properties.OfType <TabularRelationProperty>().FirstOrDefault(); if (trp != null) { rr.RelationshipIdentifier = trp.RelationshipIdentifier; } // TODO TabularRelationProperty without FK should create replationship // TODO IF we have a RelationshipIdentifier // A/ Create a Copy -> TableName + " " + RelationshipIdentifier // if any other reference exists (without RelationshipIdentifier) // B/ Rename existing TableName to TableName + " " + RelationshipIdentifier // if NO other reference exists (without RelationshipIdentifier or any other RelationshipIdentifier) // same target on this table if (!toTables.ContainsKey(rr.ToKey)) { toTables.Add(rr.ToKey, 1); } else { toTables[rr.ToKey]++; var numberOfReferencesToTheSameTable = toTables[rr.ToKey]; if (numberOfReferencesToTheSameTable > 1) { CreateTableCopyForReference(rr, model, numberOfReferencesToTheSameTable); } } model.Relationships.Add(GenerateRelationship(rr)); } } }
private void GatherReferencedTablesByFK(RelationShipRegistrations relationShipRegistrations, SqlTable sqlTable) { // TODO order of relationships from FKs should follow column (declaration) order. var fks = sqlTable.Properties.OfType <ForeignKey>(); foreach (var fk in fks) { var firstColumnMap = fk.ForeignKeyColumns[0]; var bimRelationship = new BimRelationship(firstColumnMap.ForeignKeyColumn, firstColumnMap.ReferredColumn.Table.SchemaAndTableName, firstColumnMap.ReferredColumn.Name); if (relationShipRegistrations.Contains(bimRelationship)) { continue; } relationShipRegistrations.Add(new BimRelationship(firstColumnMap.ForeignKeyColumn, firstColumnMap.ReferredColumn.Table.SchemaAndTableName, firstColumnMap.ReferredColumn.Name)); GatherReferencedTablesByFK(relationShipRegistrations, fk.ReferredTable); } }