Example #1
0
        // 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");
        }
Example #2
0
        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);
                }
            }
        }