private static IEnumerable <NavigationProperty> GenerateNavigationProperties( DataTable columnsTable, DataTable foreignKeyColumnsTable, DataTable foreignKeysTable, DataTable tablesTable, Table table, IReadOnlyCollection <Table> tables) { var props = new List <NavigationProperty>(); // get foreign keys var foreignKeys = DbUtil.GetForeignKeysByTableId( columnsTable, foreignKeysTable, foreignKeyColumnsTable, tablesTable, table.ObjectId, table.TableName); // for each foreign key, foreignKeys.ForEach(a => { var isDestinationForeignKeyAllNonNullable = IsDestinationNullable(a, columnsTable); var isSourceForeignKeyAlsoPrimaryKey = IsSourcePrimaryKey(table, a); var type = EntityDesignUtil.Singularize( NamingUtil.GetTableName(a.DestinationTableName)); var srcCol = a.Columns[0].SourceColumn; var prop = new NavigationProperty { DestinationMultiplicity = // Zero: if any source foreign key columns are nullable !isDestinationForeignKeyAllNonNullable ? Multiplicity.Zero // One: not Zero : Multiplicity.One, ForeignKey = a, // *-1, 1-0/1 Name = SourceNavPropNames.TryGetValue( a.SourceTableName + "." + string.Join("|", a.Columns.Select(b => b.SourceColumn)), out var sourcePropName) ? sourcePropName : srcCol.ToLower().EndsWith("id") && srcCol.Length > 2 ? srcCol.Substring(0, srcCol.Length - 2) : type, SourceMultiplicity = isSourceForeignKeyAlsoPrimaryKey ? Multiplicity.One : Multiplicity.Many, Type = type }; // only add if not in NavigationPropertiesToSkip if (!NavPropsToSkip.ContainsKey(table.GeneratedName + "." + prop.Name)) { props.Add(prop); } // get destination table if (tables == null) { return; } { var destTable = tables .FirstOrDefault(b => b.TableName == a.DestinationTableName); type = EntityDesignUtil.Singularize( NamingUtil.GetTableName(a.SourceTableName)); var destProp = new NavigationProperty { DestinationMultiplicity = prop.SourceMultiplicity, ForeignKey = a, InverseProperty = prop.Name, Name = DestNavPropNames.TryGetValue( a.SourceTableName + "." + a.Columns[0].SourceColumn, out var destPropName) ? destPropName : prop.SourceMultiplicity == Multiplicity.Many ? EntityDesignUtil.Pluralize(type) : type, SourceMultiplicity = prop.DestinationMultiplicity, Type = prop.SourceMultiplicity == Multiplicity.Many ? "ICollection<" + type + ">" : type }; if (destTable != null && !NavPropsToSkip.ContainsKey(destTable.GeneratedName + "." + destProp.Name)) { destTable.NavigationProperties.Add(destProp); } } }); // var isManyToMany = AreAllColumnsForeignKeys // The relationship is many-to-many only if the // relationship table only contains primary keys // of both entities, and no other fields. // 0, 1, *: 0-1, 1-0, 1->1, 1<-1, 0-*, 1-*, *-0, *-1, *-* // if 0-1, // add single, non-nullable navigation property // of foreign key destination table class, // and ensure foreign key destination table class // has non-required navigation property to current table class // if 1-0, // do nothing, as non-required navigation property will be added // when processing other side of foreign key relationship // if 1->1, // add single, non-nullable navigation property // of foreign key destination table class, // and ensure foreign key destination table class // has required navigation property to current table class // if 1<-1, // required navigation property will be added // when processing other side of foreign key relationship // if 0-*, // add public virtual ICollection of // foreign key destination table class, // and ensure foreign key destination table class // has non-required navigation property to current table class // if 1-*, // add public virtual ICollection // of foreign key destination table class, // and ensure foreign key destination table class // has required navigation property to current table class // if *-0, // do nothing, as non-required navigation property will be added // when processing other side of foreign key relationship // if *-1, // do nothing, as required navigation property will be added // when processing other side of foreign key relationship // if *-*, // well, there are no such tables, according to the // Entity Framework definition, which is that all columns // in the join table being both in the join table primary key, // and a foreign key pointing from the join table to one of the // joined tables. return(props); }
public static IEnumerable <Table> GenerateAll( DataSet ds) { var tables = DbUtil.GetTables( ds.Tables["Columns"], ds.Tables["IndexColumns"], ds.Tables["Indexes"], ds.Tables["Schemas"], ds.Tables["Tables"]); tables .ForEach(a => { a.Columns = DbUtil.GetColumnsByTableId( ds.Tables["Columns"], ds.Tables["Types"], ds.Tables["DefaultConstraints"], a.ObjectId, a.TableName); a.ForeignKeys = DbUtil.GetForeignKeysByTableId( ds.Tables["Columns"], ds.Tables["ForeignKeys"], ds.Tables["ForeignKeyColumns"], ds.Tables["Tables"], a.ObjectId, a.TableName); a.PrimaryKeyColumns = DbUtil.GetColumnsByTableIdColumnId( ds.Tables["Columns"], a.ObjectId, DbUtil.GetIndexColumnsByTableIdIndexId( ds.Tables["IndexColumns"], a.ObjectId, DbUtil.GetPrimaryKeyIndexIdByTableId( ds.Tables["Indexes"], a.ObjectId))); a.PrimaryKeyColumns .ForEach(b => { if (string.IsNullOrWhiteSpace(b)) { return; } var kcol = a.Columns .FirstOrDefault(c => c.Name == b); if (kcol != null) { kcol.IsKey = true; } }); a.ActiveColumnName = DbUtil.HasTableActiveFlag(a) ? DbUtil.GetTableActivityFieldName(a) : null; a.ActiveColumnValue = DbUtil.HasTableActiveFlag(a) && DbUtil.GetTableActivityFieldValue(a); }); tables.ForEach(a => { a.NavigationProperties .AddRange(GenerateNavigationProperties( ds.Tables["Columns"], ds.Tables["ForeignKeyColumns"], ds.Tables["ForeignKeys"], ds.Tables["Tables"], a, tables)); }); return(tables); }