// FIXME There could be a table or a view with the same name in multiple schema /!\ internal string GetSchemaNameV3(EdmxV3 edmxv3, string entityName) { var entitySetContainer = edmxv3.GetItems <LinqToEdmx.Model.StorageV3.EntityContainer>(); foreach (var container in entitySetContainer) { foreach (var entitySet in container.EntitySets.Where(es => es.Type == "Tables")) { if (entitySet.Name == entityName) { if (string.IsNullOrEmpty(entitySet.Schema1) && string.IsNullOrEmpty(entitySet.Schema)) { throw new InvalidOperationException($"[{entityName}] schema could not be null. This usually indicates a bug"); } return(entitySet.Schema ?? entitySet.Schema1); } } foreach (var entitySet in container.EntitySets.Where(es => es.Type == "Views")) { if (entitySet.EntityType.Contains(entityName)) { if (string.IsNullOrEmpty(entitySet.Schema1) && string.IsNullOrEmpty(entitySet.Schema)) { throw new InvalidOperationException($"[{entityName}] schema could not be null. This usually indicates a bug"); } return(entitySet.Schema ?? entitySet.Schema1); } } } throw new InvalidOperationException($"Unable to identify the database object schema for entity [{entityName}]. This usually indicates a bug"); }
private void GetForeignKeysV3(EdmxV3 model, LinqToEdmx.Model.StorageV3.EntityTypeStore storeTable, DatabaseModel dbModel) { var table = dbModel.Tables .Single(t => t.Name == storeTable.Name && t.Schema == GetSchemaNameV3(model, storeTable.Name)); // The foreign key informations are stored in the Association Object var associations = model.GetItems <LinqToEdmx.Model.StorageV3.Association>().Where(a => a.ReferentialConstraint.Dependent.Role == storeTable.Name); if (!associations.Any()) { // Give a chance to a reflexive constraint // TODO make sure that this is the right way to deal with this case. var endType = string.Concat(@"Self.", storeTable.Name); associations = model.GetItems <LinqToEdmx.Model.StorageV3.Association>().Where(a => a.Ends.All(e => e.Type == endType)); } // No association ? No FK then. if (!associations.Any()) { return; } foreach (var association in associations) { // The entity name could be derived if present multiple times (a table has a foreign key to himself => See ProductCategory which has a parent ProductCategory) // Te association set allows us to disambiguate the table name. var associationSet = model.GetItems <LinqToEdmx.Model.StorageV3.EntityContainer>().First().AssociationSets.Where(@as => @as.Name == association.Name).SingleOrDefault(); var entityName = association.ReferentialConstraint.Principal.Role; // Look for the table to which the columns are constrained // Remember that we could be constrained to ourself :) var principalTable = dbModel.Tables.SingleOrDefault(t => t.Name == entityName && t.Schema == GetSchemaNameV3(model, entityName)); if (principalTable == null) { entityName = associationSet.Ends.Single(e => e.Role == entityName).EntitySet; principalTable = dbModel.Tables.SingleOrDefault(t => t.Name == entityName && t.Schema == GetSchemaNameV3(model, entityName)); } if (principalTable == null) { throw new InvalidOperationException($"Unable to get foreign keys for entity with name [{entityName}]. This usually indicates a bug"); } var foreignKey = new DatabaseForeignKey { // The name of the foreign key Name = association.Name, // The table that contains the foreign key constraint (Dependent in the Edmx) Table = table, // The table to which the columns are constrained (Principal in the Edmx) PrincipalTable = principalTable, }; var end = associationSet.Ends[0]; // Finish to populate the foreign key definition with principal and dependent columns var rc = association.ReferentialConstraint; foreach (var fkCol in association.ReferentialConstraint.Principal.PropertyRefs) { var dbCol = principalTable.Columns .Single(c => c.Name == fkCol.Name); if (dbCol != null) { foreignKey.PrincipalColumns.Add(dbCol); } } foreach (var fkCol in association.ReferentialConstraint.Dependent.PropertyRefs) { // Best case scenario, the columns name are the same in both entities var dbCol = table.Columns .Single/*OrDefault*/ (c => c.Name == fkCol.Name); if (dbCol != null) { foreignKey.Columns.Add(dbCol); } } if (foreignKey.PrincipalColumns.Count > 0) { table.ForeignKeys.Add(foreignKey); } } }