private void ResolveForeignKeyConstraints(DatabaseSchema schema, Table table)
 {
     foreach (ForeignKey foreignKey in table.ForeignKeys)
     {
         foreignKey.Target = this.ResolveTableReference(schema, foreignKey.Target);
         this.FixupColumns(table, foreignKey.SourceColumns);
         this.FixupColumns(foreignKey.Target, foreignKey.TargetColumns);
     }
 }
        /// <summary>
        /// Converts the specified storage model schema into a database schema.
        /// </summary>
        /// <param name="storageModel">The storage model.</param>
        /// <returns>
        /// Instance of <see cref="DatabaseSchema"/> with <see cref="Table"/> initialized from <see cref="EntitySet"/> objects in the storage model.
        /// </returns>
        public DatabaseSchema Convert(EntityModelSchema storageModel)
        {
            DatabaseSchema schema = new DatabaseSchema();

            foreach (EntityContainer container in storageModel.EntityContainers)
            {
                var entitySetToTableMapping = this.ConvertEntitySetsToTables(schema, container);
                this.ConvertAssociationSetsToForeignKeys(container, entitySetToTableMapping);
            }

            this.ConvertFunctionsToDatabaseFunctions(storageModel, schema);

            return schema;
        }
        private Dictionary<EntitySet, Table> ConvertEntitySetsToTables(DatabaseSchema schema, EntityContainer container)
        {
            Dictionary<EntitySet, Table> entitySetToTableMapping = new Dictionary<EntitySet, Table>();

            foreach (EntitySet entitySet in container.EntitySets)
            {
                Table table = new Table(container.Name, entitySet.Name);
                schema.Tables.Add(table);
                entitySetToTableMapping.Add(entitySet, table);
                var type = entitySet.EntityType;
                var pk = new PrimaryKey("PK_" + table.Name);
                Dictionary<MemberProperty, Column> propertyToColumnMap = new Dictionary<MemberProperty, Column>();
                foreach (MemberProperty prop in type.Properties)
                {
                    var column = this.ConvertPropertyToColumn(prop);
                    propertyToColumnMap.Add(prop, column);

                    if (prop.IsPrimaryKey)
                    {
                        pk.Columns.Add(column);
                    }

                    table.Columns.Add(column);
                }

                if (pk.Columns.Count > 0)
                {
                    table.PrimaryKey = pk;
                }

                foreach (EdmUniqueConstraint edmUniqueConstraint in type.EdmUniqueConstraints)
                {
                    var uniqueConstraint = new UniqueConstraint("UC_" + table.Name + "_" + edmUniqueConstraint.Name);
                    foreach (var prop in edmUniqueConstraint.Properties)
                    {
                        Column column;
                        ExceptionUtilities.Assert(propertyToColumnMap.TryGetValue(prop, out column), "Edm Unique Constraint's property '{0}' is not found on entity type '{1}'.", prop.Name, type.FullName);
                        uniqueConstraint.Add(column);
                    }

                    table.Add(uniqueConstraint);
                }
            }

            return entitySetToTableMapping;
        }
        /// <summary>
        /// Resolves references in the database model by converting <see cref="TableReference" />
        /// instances to <see cref="Table" /> and <see cref="ColumnReference"/> to <see cref="Column"/>.
        /// </summary>
        /// <param name="schema">Database schema to fixup</param>
        public override void Fixup(DatabaseSchema schema)
        {
            foreach (Table table in schema.Tables.Concat(schema.Views.Cast<Table>()))
            {
                if (table.PrimaryKey != null)
                {
                    this.ResolveColumnsInConstraint(table, table.PrimaryKey);
                }

                foreach (var constraint in table.UniqueConstraints)
                {
                    this.ResolveColumnsInConstraint(table, constraint);
                }

                this.ResolveForeignKeyConstraints(schema, table);
            }
        }
        private Table ResolveTableReference(DatabaseSchema schema, Table table)
        {
            TableReference tableRef = table as TableReference;
            if (tableRef == null)
            {
                return table;
            }

            var result = schema.Tables.Concat(schema.Views.Cast<Table>())
                .Where(t => t.Catalog == tableRef.Catalog && t.Schema == tableRef.Schema && t.Name == tableRef.Name)
                .SingleOrDefault();

            if (result == null)
            {
                throw new TaupoInvalidOperationException("The table or view '" + tableRef + "' was not found in the schema.");
            }

            return result;
        }
 /// <summary>
 /// Performs the fixup.
 /// </summary>
 /// <param name="schema">Database schema</param>
 public abstract void Fixup(DatabaseSchema schema);
        /// <summary>
        /// Serializes a DatabaseSchema graph to C# code that will re-construct the graph
        /// </summary>
        /// <param name="schema">Schema to be serialized</param>
        public void Serialize(DatabaseSchema schema)
        {
            IEnumerable<string> requiredNamespaces = new List<string>()
            {
                typeof(DatabaseSchema).Namespace,
            };
           requiredNamespaces = requiredNamespaces.Union(this.TypeConstructorGenerator.GetCodeNamespaces());

            this.Writer.WriteLine("namespace MyNamespace");
            this.Writer.WriteLine("{");
            this.Writer.Indent++;

            foreach (string ns in requiredNamespaces)
            {
                this.Writer.WriteLine("using {0};", ns);
            }

            this.Writer.WriteLine();

            this.Writer.WriteLine("public class Test");
            this.Writer.WriteLine("{");
            this.Writer.Indent++;

            this.Writer.WriteLine("public DatabaseSchema BuildSchema()");
            this.Writer.WriteLine("{");
            this.Writer.Indent++;

            this.Writer.WriteLine("DatabaseSchema schema = new DatabaseSchema()");
            this.Writer.WriteLine("{");
            this.Writer.Indent++;

            foreach (var table in schema.Tables.Concat(schema.Views))
            {
                this.Writer.WriteLine("new {0}({1})", table.GetType().Name, BuildSchemaObjectCSV(table, this.SpecificationLevel));
                this.Writer.WriteLine("{");
                this.Writer.Indent++;

                foreach (var column in table.Columns)
                {
                    this.Writer.WriteLine("new Column(\"{0}\", {1}),", column.Name, this.TypeConstructorGenerator.GetDataTypeConstructorCode(column.ColumnType));
                }

                if (table.PrimaryKey != null)
                {
                    this.Writer.WriteLine();
                    this.Writer.WriteLine("new PrimaryKey({0})", BuildSchemaObjectCSV(table.PrimaryKey, this.SpecificationLevel));
                    this.Writer.Indent++;
                    this.Writer.WriteLine(".WithKeyColumns({0}),", BuildColumnNameCSV(table.PrimaryKey.Columns));
                    this.Writer.Indent--;
                }

                if (table.UniqueConstraints.Count > 0)
                {
                    this.Writer.WriteLine();
                    foreach (var constraint in table.UniqueConstraints)
                    {
                        this.Writer.WriteLine("new UniqueConstraint({0})", BuildSchemaObjectCSV(constraint, this.SpecificationLevel));
                        this.Writer.Indent++;
                        this.Writer.WriteLine(".WithUniqueColumns({0}),", BuildColumnNameCSV(constraint.Columns));
                        this.Writer.Indent--;
                    }
                }

                if (table.ForeignKeys.Count > 0)
                {
                    this.Writer.WriteLine();
                    foreach (var fk in table.ForeignKeys)
                    {
                        this.Writer.WriteLine("new ForeignKey({0})", BuildSchemaObjectCSV(fk, this.SpecificationLevel));
                        this.Writer.Indent++;

                        if (fk.SourceColumns.Count == 1)
                        {
                            this.Writer.WriteLine(".WithSourceColumn(\"{0}\")", fk.SourceColumns[0].Name);
                        }
                        else
                        {
                            this.Writer.WriteLine(".WithSourceColumns({0})", BuildColumnNameCSV(fk.SourceColumns));
                        }

                        this.Writer.WriteLine(".References(new TableReference({0}), {1}),", BuildSchemaObjectCSV(fk.Target, this.SpecificationLevel), BuildColumnNameCSV(fk.TargetColumns));
                        this.Writer.Indent--;
                    }
                }

                this.Writer.Indent--;
                this.Writer.WriteLine("},"); // Table constructor
            }

            this.Writer.Indent--;
            this.Writer.WriteLine("}.Resolve();"); // DatabaseSchema constructor

            this.Writer.WriteLine();
            this.Writer.WriteLine("return schema;");

            this.Writer.Indent--;
            this.Writer.WriteLine("}"); // method

            this.Writer.Indent--;
            this.Writer.WriteLine("}"); // class

            this.Writer.Indent--;
            this.Writer.WriteLine("}"); // namespace
        }
        private void ConvertFunctionsToDatabaseFunctions(EntityModelSchema storageModel, DatabaseSchema schema)
        {
            var composableFunctionsToConvert = storageModel.Functions
                .Where(f =>
                {
                    var a = f.Annotations.OfType<StoreFunctionMetadataAnnotation>().SingleOrDefault();
                    return a == null || (!a.IsBuiltIn && a.IsComposable);
                });

            var nonComposableFunctionsToConvert = storageModel.Functions
                .Where(f =>
                {
                    var a = f.Annotations.OfType<StoreFunctionMetadataAnnotation>().SingleOrDefault();
                    return a != null && !a.IsBuiltIn && !a.IsComposable;
                });

            if (composableFunctionsToConvert.Any() && this.DatabaseFunctionBodyResolver != null)
            {
                foreach (var function in composableFunctionsToConvert)
                {
                    var databaseFunction = this.ConvertToDatabaseFunction(function);
                    this.DatabaseFunctionBodyResolver.ResolveFunctionBody(databaseFunction);
                    schema.Add(databaseFunction);
                }
            }

            if (nonComposableFunctionsToConvert.Any() && this.DatabaseFunctionBodyResolver != null)
            {
                foreach (var function in nonComposableFunctionsToConvert)
                {
                    var storedProcedure = this.ConvertToStoredProcedure(function);
                    this.DatabaseFunctionBodyResolver.ResolveStoredProcedureBody(storedProcedure);
                    if (this.ShouldGenerateCommandText(function))
                    {
                        this.AddCommandTextToAnnotation(function, storedProcedure.Body);
                    }
                    else
                    {
                        schema.Add(storedProcedure);
                    }
                }
            }
        }