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
 public XRoot(EdmxV3 root)
 {
     _xDocument  = new XDocument(root.Untyped);
     _rootObject = root;
 }
Example #3
0
 public XRootNamespace(EdmxV3 root)
 {
     _doc        = new XDocument(root.Untyped);
     _rootObject = root;
 }
Example #4
0
        public DatabaseModel Create(string edmxPath, DatabaseModelFactoryOptions options)
        {
            if (string.IsNullOrEmpty(edmxPath))
            {
                throw new ArgumentException(@"invalid path", nameof(edmxPath));
            }
            if (!File.Exists(edmxPath))
            {
                throw new ArgumentException($"Edmx file not found: {edmxPath}");
            }

            var schemas = options.Schemas;
            var tables  = options.Tables;

            var dbModel = new DatabaseModel
            {
                DatabaseName  = Path.GetFileNameWithoutExtension(edmxPath),
                DefaultSchema = schemas.Count() > 0 ? schemas.First() : "dbo"
            };

            // Detect the EDMX file version
            XDocument edmxFile = XDocument.Load(edmxPath);

            var edmxVersion = ((XElement)edmxFile.FirstNode).FirstAttribute.Value;

            if (string.Compare(edmxVersion, @"3.0", StringComparison.InvariantCultureIgnoreCase) == 0)
            {
                var edmxv3 = EdmxV3.Load(edmxPath);
                if (!edmxv3.Runtimes[0].StorageModels.StorageSchema.Provider.Equals("System.Data.SqlClient", StringComparison.Ordinal))
                {
                    throw new NotSupportedException("Only SQL Server EDMX files are currently supported");
                }

                var items = edmxv3.GetItems <LinqToEdmx.Model.StorageV3.EntityTypeStore>();

                foreach (var item in items)
                {
                    var dbTable = new DatabaseTable
                    {
                        Name   = item.Name,
                        Schema = GetSchemaNameV3(edmxv3, item.Name),
                    };

                    GetColumnsV3(item, dbTable, edmxv3);
                    GetPrimaryKeyV3(item, dbTable);

                    dbModel.Tables.Add(dbTable);
                }

                foreach (var item in items)
                {
                    GetForeignKeysV3(edmxv3, item, dbModel);
                }
            }
            else
            {
                throw new NotSupportedException("Only V3 edmx files supported.");
            }

            return(dbModel);
        }
Example #5
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);
                }
            }
        }