public StarModel Refine(StarModel starModel) { FactTable fact = starModel.FactTable; // Create new dimension List <StarColumn> stringColumns = new List <StarColumn>(); if (fact.Columns.Count(x => x.DataType.IsString()) == 0) { return(starModel); } var surrogateKey = new StarColumn(1, "SurKey", new DataType(OleDbType.Integer), StarColumnType.Key | StarColumnType.SurrogateKey); stringColumns.Add(surrogateKey); var junkColumns = fact.Columns.Where(x => x.DataType.IsString()).Select(c => new JunkColumn(c)); stringColumns.AddRange(junkColumns); JunkDimension dimension = new JunkDimension($"Junk_{fact.Name}", stringColumns, fact.TableReference); surrogateKey.TableRef = dimension; dimension.Constraints.PrimaryKey.Columns.Add(surrogateKey); dimension.Constraints.Uniques.Add(new Unique(stringColumns)); // Fact relation to new dimension var foreignColumn = new StarColumn(0, $"{dimension.Name}_Key", new DataType(OleDbType.Integer), StarColumnType.Key); foreignColumn.TableRef = fact; fact.Columns.Add(foreignColumn); // Remove string columns from fact table starModel.FactTable.Columns.RemoveAll(c => c.DataType.IsString()); StarRelation r = new StarRelation(dimension, starModel.FactTable, new List <StarColumn>() { surrogateKey }, new List <StarColumn>() { foreignColumn }, Cardinality.ManyToOne); fact.Relations.Add(r); dimension.Relations.Add(r); starModel.Dimensions.Add(dimension); return(starModel); }
public override StarModel TranslateModel(StarModel starModel) { //All fact tables across all star models FactTable factTable = starModel.FactTable; List <Dimension> temporaryDimensions = starModel.Dimensions; // Case 1, if dimensions have been found, simply flatten them // Case 2, if dimensions have *not* been found, find all connected tables to the fact table and flatten them. // Case 2 if (temporaryDimensions.Count == 0) { List <Table> tables = factTable.TableReference.Relations .Where(x => factTable.TableReference == x.LinkTable && x.Cardinality == Cardinality.ManyToOne && x.AnchorTable != factTable.TableReference) .Select(x => x.AnchorTable) .ToList(); temporaryDimensions = tables.Select(table => new Dimension(table)).ToList(); } // Case 1 foreach (var dim in temporaryDimensions) { var tableRef = dim.TableReference; var newColumns = Flatten(tableRef, new List <Table>() { tableRef }); dim.Columns.AddRange(newColumns); dim.Columns.ForEach(x => x.TableRef = dim); } factTable.Relations.Clear(); // Add relations from fact table to all dimensions foreach (var dimension in temporaryDimensions) { var starRelation = new StarRelation(dimension, factTable, Cardinality.ManyToOne); factTable.Relations.Add(starRelation); dimension.Relations.Add(starRelation); } starModel.Dimensions.AddRange(temporaryDimensions); return(starModel); }
public StarModel Refine(StarModel starModel) { var factTable = starModel.FactTable; // If any date/time dimension already exists if (starModel.Dimensions.Any(d => d.Name.Contains("time") || d.Name.Contains("date"))) { return(starModel); } // Create date and time dimension for model. These are also used for roleplaying DateDimension actualDateDimension = CreateDateDimension(); TimeDimension actualTimeDimension = CreateTimeDimension(); // These can either be the actual dimension or roleplaying dimensions DateDimension dateDimension = null; TimeDimension timeDimension = null; // Add a date and/or time dimension to all columns that can express date or time foreach (var temporalColumn in factTable.Columns.Where(c => c.DataType.IsTemporal()).ToList()) { // If date, only add date dimension, likewise with time. If a date/time dimension is already in use, // then use that for roleplaying switch (temporalColumn.DataType.Type) { case OleDbType.DBTime: timeDimension = timeDimension != null ? new TimeDimension(actualTimeDimension) : actualTimeDimension; break; case OleDbType.Date: case OleDbType.DBDate: dateDimension = dateDimension != null ? new DateDimension(actualDateDimension) : actualDateDimension; break; case OleDbType.DBTimeStamp: dateDimension = dateDimension != null ? new DateDimension(actualDateDimension) : actualDateDimension; timeDimension = timeDimension != null ? new TimeDimension(actualTimeDimension) : actualTimeDimension; break; } // If time dimension is set, then add it to the model and add a relation if (timeDimension != null) { starModel.Dimensions.Add(timeDimension); var timeForeignKey = new StarColumn(factTable.Columns.Count + 1, $"{temporalColumn.Name}_Time_Key", new DataType(OleDbType.Integer), StarColumnType.Key); timeForeignKey.ColumnRef = temporalColumn.ColumnRef; var relation = new StarRelation(timeDimension, factTable, new List <StarColumn> { timeDimension.Columns[0] }, new List <StarColumn> { timeForeignKey }, Cardinality.ManyToOne); factTable.Relations.Add(relation); timeDimension.Relations.Add(relation); factTable.Columns.Add(timeForeignKey); factTable.Constraints.PrimaryKey.Columns.Add(timeForeignKey); } // If date dimension is set, then add it to the model and add a relation if (dateDimension != null) { starModel.Dimensions.Add(dateDimension); var dateForeignKey = new StarColumn(factTable.Columns.Count + 1, $"{temporalColumn.Name}_Date_Key", new DataType(OleDbType.Integer), StarColumnType.Key); dateForeignKey.ColumnRef = temporalColumn.ColumnRef; var relation = new StarRelation(dateDimension, factTable, new List <StarColumn> { dateDimension.Columns[0] }, new List <StarColumn> { dateForeignKey }, Cardinality.ManyToOne); factTable.Relations.Add(relation); dateDimension.Relations.Add(relation); factTable.Columns.Add(dateForeignKey); factTable.Constraints.PrimaryKey.Columns.Add(dateForeignKey); } temporalColumn.ColumnType = StarColumnType.DescriptiveMeasure; // Cleanup factTable.Columns.Remove(temporalColumn); } return(starModel); }