protected virtual void WriteClass(CodeWriter writer, Table table, Database schema, GenerationContext context)
        {
            writer.WriteLine();

            string entityBase = context.Parameters.EntityBase;
            if (string.IsNullOrEmpty(entityBase))
                entityBase = schema.EntityBase;

            var specifications = SpecificationDefinition.Partial;
            if (table.Type.AccessModifierSpecified)
                specifications |= GetSpecificationDefinition(table.Type.AccessModifier);
            else
                specifications |= SpecificationDefinition.Public;
            if (table.Type.ModifierSpecified)
                specifications |= GetSpecificationDefinition(table.Type.Modifier);

            var tableAttribute = NewAttributeDefinition<TableAttribute>();
            tableAttribute["Name"] = table.Name;
            using (writer.WriteAttribute(tableAttribute))
            using (writer.WriteClass(specifications,
                                     table.Type.Name, entityBase, context.Parameters.EntityInterfaces))
            {
                WriteClassHeader(writer, table, context);
                WriteCustomTypes(writer, table, schema, context);
                WriteClassExtensibilityDeclarations(writer, table, context);
                WriteClassProperties(writer, table, context);
                if (context.Parameters.GenerateEqualsHash)
                    WriteClassEqualsAndHash(writer, table, context);
                WriteClassChildren(writer, table, schema, context);
                WriteClassParents(writer, table, schema, context);
                WriteClassChildrenAttachment(writer, table, schema, context);
                WriteClassCtor(writer, table, schema, context);
            }
        }
 protected virtual void WriteDataContextProcedures(CodeWriter writer, DbLinq.Schema.Dbml.Database schema, GenerationContext context)
 {
     foreach (var procedure in schema.Functions)
     {
         WriteDataContextProcedure(writer, procedure, context);
     }
 }
Beispiel #3
0
        protected override void LoadConstraints(Database schema, SchemaName schemaName, IDbConnection conn, NameFormat nameFormat, Names names)
        {
            var constraints = ReadConstraints(conn, schemaName.DbName);

            //sort tables - parents first (this is moving to SchemaPostprocess)
            //TableSorter.Sort(tables, constraints); 

            foreach (DataConstraint keyColRow in constraints)
            {
                //find my table:
                string fullKeyDbName = GetFullDbName(keyColRow.TableName, keyColRow.TableSchema);
                DbLinq.Schema.Dbml.Table table = schema.Tables.FirstOrDefault(t => fullKeyDbName == t.Name);
                if (table == null)
                {
                    bool ignoreCase = true;
                    table = schema.Tables.FirstOrDefault(t => 0 == string.Compare(fullKeyDbName, t.Name, ignoreCase));
                    if (table == null)
                    {
                        WriteErrorLine("ERROR L46: Table '" + keyColRow.TableName + "' not found for column " + keyColRow.ColumnName);
                        continue;
                    }
                }

                bool isForeignKey = keyColRow.ConstraintName != "PRIMARY"
                                    && keyColRow.ReferencedTableName != null;

                if (isForeignKey)
                {
                    LoadForeignKey(schema, table, keyColRow.ColumnName, keyColRow.TableName, keyColRow.TableSchema,
                                   keyColRow.ReferencedColumnName, keyColRow.ReferencedTableName, keyColRow.ReferencedTableSchema,
                                   keyColRow.ConstraintName, nameFormat, names);
                }

            }
        }
 protected virtual void CheckNames(Database schema)
 {
     CheckNames(schema,
                column => "Contents",
                association => association.ThisKey + association.Member,
                association => association.Member + association.Type);
 }
 protected virtual void WriteDataContextCtors(CodeWriter writer, Database schema, Type contextBaseType, GenerationContext context)
 {
     // ctor taking a connections tring
     WriteDataContextCtor(writer, schema, contextBaseType,
            new[] { new ParameterDefinition { Name = "connectionString", Type = typeof(string) } },
            new[] { "connectionString" },
            new[] { typeof(string) },
            context);
     // the two constructors below have the same prototype, so they are mutually exclusive
     // the base class requires a IVendor
     if (!WriteDataContextCtor(writer, schema, contextBaseType,
                          new[] { new ParameterDefinition { Name = "connection", Type = typeof(IDbConnection) } },
                          new[] { "connection", writer.GetNewExpression(writer.GetMethodCallExpression(writer.GetLiteralFullType(context.SchemaLoader.Vendor.GetType()))) },
                          new[] { typeof(IDbConnection), typeof(IVendor) },
                          context))
     {
         // OR the base class requires no IVendor
         WriteDataContextCtor(writer, schema, contextBaseType,
                              new[] { new ParameterDefinition { Name = "connection", Type = typeof(IDbConnection) } },
                              new[] { "connection" },
                              new[] { typeof(IDbConnection) },
                              context);
     }
     // ctor(string, MappingSource)
     WriteDataContextCtor(writer, schema, contextBaseType,
            new[] {
                new ParameterDefinition { Name = "connection", Type = typeof(string) },
                new ParameterDefinition { Name = "mappingSource", Type = typeof(MappingSource) },
            },
            new[] { "connection", "mappingSource" },
            new[] { typeof(string), typeof (MappingSource) },
            context);
     // ctor(IDbConnection, MappingSource)
     WriteDataContextCtor(writer, schema, contextBaseType,
             new[] {
                 new ParameterDefinition { Name = "connection", Type = typeof(IDbConnection) },
                 new ParameterDefinition { Name = "mappingSource", Type = typeof(MappingSource) },
             },
             new[] { "connection", "mappingSource" },
             new[] { typeof(IDbConnection), typeof(MappingSource) },
             context);
     // just in case you'd like to specify another vendor than the one who helped generating this file
     WriteDataContextCtor(writer, schema, contextBaseType,
             new[] {
                 new ParameterDefinition { Name = "connection", Type = typeof(IDbConnection) },
                 new ParameterDefinition { Name = "vendor", Type = typeof(IVendor) },
             },
             new[] { "connection", "vendor" },
             new[] { typeof(IDbConnection), typeof(IVendor) },
             context);
     WriteDataContextCtor(writer, schema, contextBaseType,
             new[] {
                 new ParameterDefinition { Name = "connection", Type = typeof(IDbConnection) },
                 new ParameterDefinition { Name = "mappingSource", Type = typeof(MappingSource) },
                 new ParameterDefinition { Name = "vendor", Type = typeof(IVendor) },
             },
             new[] { "connection", "mappingSource", "vendor" },
             new[] { typeof(IDbConnection), typeof(MappingSource), typeof(IVendor) },
             context);
 }
 /// <summary>
 /// Generates a Visual Basic source code wrapper for the database schema objects.
 /// </summary>
 /// <param name="database"></param>
 /// <param name="filename"></param>
 public void GenerateVisualBasic(Database database, string filename)
 {
     using (Stream stream = File.Open(filename, FileMode.Create))
     {
         using (StreamWriter writer = new StreamWriter(stream))
         {
             new VBCodeProvider().CreateGenerator(writer).GenerateCodeFromNamespace(GenerateCodeDomModel(database), writer, new CodeGeneratorOptions() { BracingStyle = "C" });
         }
     }
 }
 public void Write(TextWriter textWriter, Database dbSchema, GenerationContext context)
 {
     Context = context;
     Provider.CreateGenerator(textWriter).GenerateCodeFromNamespace(
         GenerateCodeDomModel(dbSchema), textWriter, 
         new CodeGeneratorOptions() {
             BracingStyle = "C",
             IndentString = "\t",
         });
 }
        protected override void LoadConstraints(Database schema, SchemaName schemaName, IDbConnection conn, NameFormat nameFormat, Names names)
        {
            //TableSorter.Sort(tables, constraints); //sort tables - parents first

            var constraints = ReadConstraints(conn, schemaName.DbName);

            var allKeys2 = ReadForeignConstraints(conn, schemaName.DbName);
            var foreignKeys = allKeys2.Where(k => k.ConstraintType == "FOREIGN KEY").ToList();
            var primaryKeys = allKeys2.Where(k => k.ConstraintType == "PRIMARY KEY").ToList();


            foreach (DataConstraint keyColRow in constraints)
            {
                //find my table:
                string constraintFullDbName = GetFullDbName(keyColRow.TableName, keyColRow.TableSchema);
                DbLinq.Schema.Dbml.Table table = schema.Tables.FirstOrDefault(t => constraintFullDbName == t.Name);
                if (table == null)
                {
                    WriteErrorLine("ERROR L138: Table '" + keyColRow.TableName + "' not found for column " + keyColRow.ColumnName);
                    continue;
                }

                //todo: must understand better how PKEYs are encoded.
                //In Sasha's DB, they don't end with "_pkey", you need to rely on ReadForeignConstraints().
                //In Northwind, they do end with "_pkey".
                bool isPrimaryKey = keyColRow.ConstraintName.EndsWith("_pkey")
                    || primaryKeys.Count(k => k.ConstraintName == keyColRow.ConstraintName) == 1;

                if (isPrimaryKey)
                {
                    //A) add primary key
                    DbLinq.Schema.Dbml.Column primaryKeyCol = table.Type.Columns.First(c => c.Name == keyColRow.ColumnName);
                    primaryKeyCol.IsPrimaryKey = true;
                }
                else
                {
                    DataForeignConstraint dataForeignConstraint = foreignKeys.FirstOrDefault(f => f.ConstraintName == keyColRow.ConstraintName);

                    if (dataForeignConstraint == null)
                    {
                        string msg = "Missing data from 'constraint_column_usage' for foreign key " + keyColRow.ConstraintName;
                        WriteErrorLine(msg);
                        //throw new ApplicationException(msg);
                        continue; //as per Andrus, do not throw. //putting together an Adnrus_DB test case.
                    }

                    LoadForeignKey(schema, table, keyColRow.ColumnName, keyColRow.TableName, keyColRow.TableSchema,
                                   dataForeignConstraint.ColumnName, dataForeignConstraint.ReferencedTableName,
                                   dataForeignConstraint.ReferencedTableSchema,
                                   keyColRow.ConstraintName, nameFormat, names);

                }

            }
        }
        protected virtual void WriteClasses(CodeWriter writer, Database schema, GenerationContext context)
        {
            IEnumerable<Table> tables = schema.Tables;

            var types = context.Parameters.GenerateTypes;
            if (types.Count > 0)
                tables = tables.Where(t => types.Contains(t.Type.Name));

            foreach (var table in tables)
                WriteClass(writer, table, schema, context);
        }
        /// <summary>
        /// Loads the foreign key.
        /// </summary>
        /// <param name="schema">The schema.</param>
        /// <param name="table">The table.</param>
        /// <param name="columnName">Name of the column.</param>
        /// <param name="tableName">Name of the table.</param>
        /// <param name="tableSchema">The table schema.</param>
        /// <param name="referencedColumnName">Name of the referenced column.</param>
        /// <param name="referencedTableName">Name of the referenced table.</param>
        /// <param name="referencedTableSchema">The referenced table schema.</param>
        /// <param name="constraintName">Name of the constraint.</param>
        /// <param name="nameFormat">The name format.</param>
        /// <param name="names">The names.</param>
        protected virtual void LoadForeignKey(Database schema, Table table, string columnName, string tableName, string tableSchema,
            string referencedColumnName, string referencedTableName, string referencedTableSchema,
            string constraintName,
            NameFormat nameFormat, Names names)
        {
            var foreignKey = BuildForeignKey(names.ColumnsNames[tableName], columnName);
            var reverseForeignKey = BuildForeignKey(names.ColumnsNames[referencedTableName], referencedColumnName);

            var associationName = CreateAssociationName(tableName, tableSchema,
                referencedTableName, referencedTableSchema, constraintName, foreignKey, nameFormat);

            //both parent and child table get an [Association]
            var assoc = new Association();
            assoc.IsForeignKey = true;
            assoc.Name = constraintName;
            assoc.Type = null;
            assoc.ThisKey = foreignKey;
            assoc.OtherKey = reverseForeignKey;
            assoc.Member = associationName.ManyToOneMemberName;
            assoc.CardinalitySpecified = false;
            // TODO: generate assoc.Cardinality?
            table.Type.Associations.Add(assoc);

            //and insert the reverse association:
            var reverseAssociation = new Association();
            reverseAssociation.Name = constraintName;
            reverseAssociation.Type = table.Type.Name;
            reverseAssociation.Member = associationName.OneToManyMemberName;
            reverseAssociation.CardinalitySpecified = false;
            // TODO: generate reverseAssociation.Cardinality?
            reverseAssociation.ThisKey = reverseForeignKey;
            reverseAssociation.OtherKey = foreignKey;
            reverseAssociation.DeleteRule = "NO ACTION";

            string referencedFullDbName = GetFullDbName(referencedTableName, referencedTableSchema);
            var referencedTable = schema.Tables.FirstOrDefault(t => referencedFullDbName == t.Name);
            if (referencedTable == null)
            {
                //try case-insensitive match 
                //reason: MySql's Key_Column_Usage table contains both 'Northwind' and 'northwind'
                referencedTable = schema.Tables.FirstOrDefault(t => referencedFullDbName.ToLower() == t.Name.ToLower());
            }

            if (referencedTable == null)
            {
                ReportForeignKeyError(schema, referencedFullDbName);
            }
            else
            {
                referencedTable.Type.Associations.Add(reverseAssociation);
                assoc.Type = referencedTable.Type.Name;
            }
        }
        protected override void LoadConstraints(Database schema, SchemaName schemaName, IDbConnection conn, NameFormat nameFormat, Names names)
        {
            var constraints = ReadConstraints(conn, schemaName.DbName);

            foreach (DataConstraint constraint in constraints)
            {
                //find my table:
                string constraintFullDbName = GetFullDbName(constraint.TableName, constraint.TableSchema);
                DbLinq.Schema.Dbml.Table table = schema.Tables.FirstOrDefault(t => constraintFullDbName == t.Name);
                if (table == null)
                {
                    WriteErrorLine("ERROR L100: Table '" + constraint.TableName + "' not found for column " + constraint.ColumnNameList);
                    continue;
                }

                //if (table.Name.StartsWith("E"))
                //    Logger.Write("---Dbg");

                if (constraint.ConstraintType == "P")
                {
                    //A) add primary key
                    DbLinq.Schema.Dbml.Column pkColumn = table.Type.Columns.Where(c => constraint.ColumnNames.Contains(c.Name)).First();
                    pkColumn.IsPrimaryKey = true;
                }
                else if (constraint.ConstraintType == "R")
                {
                    //if not PRIMARY, it's a foreign key. (constraint_type=="R")
                    //both parent and child table get an [Association]
                    DataConstraint referencedConstraint = constraints.FirstOrDefault(c => c.ConstraintName == constraint.ReverseConstraintName);
                    if (constraint.ReverseConstraintName == null || referencedConstraint == null)
                    {
                        WriteErrorLine("ERROR L127: given R_contraint_name='" + constraint.ReverseConstraintName + "', unable to find parent constraint");
                        continue;
                    }

                    LoadForeignKey(schema, table, constraint.ColumnNameList, constraint.TableName, constraint.TableSchema,
                                   referencedConstraint.ColumnNameList, referencedConstraint.TableName,
                                   referencedConstraint.TableSchema,
                                   constraint.ConstraintName, nameFormat, names);

                }
                // custom type, this is a trigger
                else if (constraint.ConstraintType == "T" && constraint.ColumnNames.Count == 1)
                {
                    var column = table.Type.Columns.Where(c => c.Name == constraint.ColumnNames[0]).First();
                    column.Expression = constraint.Expression;
                    column.IsDbGenerated = true;
                }
            }

            //GuessSequencePopulatedFields(schema);
        }
        protected override void LoadConstraints(Database schema, SchemaName schemaName, IDbConnection conn, NameFormat nameFormat, Names names)
        {
            //TableSorter.Sort(tables, constraints); //sort tables - parents first

            var foreignKeys = ReadConstraints(conn, schemaName.DbName);

            foreach (DataConstraint keyColRow in foreignKeys)
            {
                //find my table:
                string constraintFullDbName = GetFullDbName(keyColRow.TableName, keyColRow.TableSchema);
                DbLinq.Schema.Dbml.Table table = schema.Tables.FirstOrDefault(t => constraintFullDbName == t.Name);
                if (table == null)
                {
                    WriteErrorLine("ERROR L138: Table '"
                                              + keyColRow.TableName
                                              + "' not found for column "
                                              + keyColRow.ColumnName);
                    continue;
                }

                if (keyColRow.ConstraintType.Equals("P")) //'PRIMARY KEY'
                {
                    //foreach (string pk_name in keyColRow.column_name_primaries)
                    //{
                    DbLinq.Schema.Dbml.Column primaryKeyCol = table.Type.Columns.First(c => c.Name == keyColRow.ColumnName);
                    primaryKeyCol.IsPrimaryKey = true;
                    //}
                    continue;
                }

                if (keyColRow.ConstraintType.Equals("R")) //'FOREIGN KEY'
                {
                    // This is very bad...
                    if (!names.ColumnsNames[keyColRow.ReferencedTableName].ContainsKey(keyColRow.ReferencedColumnName))
                        continue;

                    LoadForeignKey(schema, table, keyColRow.ColumnName, keyColRow.TableName,
                                   keyColRow.TableSchema,
                                   keyColRow.ReferencedColumnName, keyColRow.ReferencedTableName,
                                   keyColRow.ReferencedTableSchema,
                                   keyColRow.ConstraintName, nameFormat, names);

                }

            }
        }
        protected override void LoadStoredProcedures(Database schema, SchemaName schemaName, IDbConnection conn, NameFormat nameFormat)
        {
            var parameters = ReadParameters(conn, schemaName.DbName);
            foreach (var parameter in parameters)
            {
                var procedureName = CreateProcedureName(parameter.ProcedureName, parameter.Schema, nameFormat);

                Function function = schema.Functions.SingleOrDefault(f => f.Method == procedureName.MethodName);
                if (function == null)
                {
                    function = new Function { Name = procedureName.DbName, Method = procedureName.MethodName };
                    schema.Functions.Add(function);
                }

                if (parameter.Name == null)
                {
                    var returnParameter = new Return();
                    returnParameter.DbType = parameter.Type.SqlType;
                    returnParameter.Type = MapDbType(parameter.Name, parameter.Type).ToString();

                    function.IsComposable = true;
                    function.Return = returnParameter;
                }
                else
                {
                    var functionParameter = new Parameter();
                    functionParameter.DbType = parameter.Type.SqlType;
                    functionParameter.Type = MapDbType(parameter.Name, parameter.Type).ToString();
                    if (parameter.In)
                    {
                        if (parameter.Out)
                            functionParameter.Direction = DbLinq.Schema.Dbml.ParameterDirection.InOut;
                        else
                            functionParameter.Direction = DbLinq.Schema.Dbml.ParameterDirection.In;
                    }
                    else
                        functionParameter.Direction = DbLinq.Schema.Dbml.ParameterDirection.Out;

                    var parameterName = CreateParameterName(parameter.Name, nameFormat);
                    functionParameter.Name = parameterName.CallName;

                    function.Parameters.Add(functionParameter);
                }
            }
        }
 protected virtual bool WriteDataContextCtor(CodeWriter writer, Database schema, Type contextBaseType,
     ParameterDefinition[] parameters, string[] baseCallParameterNames, Type[] baseCallParameterTypes,
     GenerationContext context)
 {
     // if we have a contextBaseType, then check that we can do it
     if (contextBaseType != null)
     {
         var ctor = contextBaseType.GetConstructor(baseCallParameterTypes);
         if (ctor == null)
             return false;
     }
     using (writer.WriteCtor(SpecificationDefinition.Public, schema.Class, parameters, baseCallParameterNames))
     {
         writer.WriteLine(writer.GetStatement(writer.GetMethodCallExpression("OnCreated")));
     }
     writer.WriteLine();
     return true;
 }
 /// <summary>
 /// Checks for name conflicts, given lambdas to correct on conflicts
 /// </summary>
 /// <param name="schema"></param>
 /// <param name="tableNamedAssociationRenamer"></param>
 /// <param name="columnNamedAssociationRenamer"></param>
 protected virtual void CheckConstraintsName(Database schema,
                               Func<Association, string> tableNamedAssociationRenamer,
                               Func<Association, string> columnNamedAssociationRenamer)
 {
     foreach (var table in schema.Tables)
     {
         foreach (var association in table.Type.Associations)
         {
             var localAssociation = association;
             if (association.Member == table.Type.Name)
                 association.Member = tableNamedAssociationRenamer(association);
             else if ((from column in table.Type.Columns where column.Member == localAssociation.Member select column).FirstOrDefault() != null)
             {
                 association.Member = columnNamedAssociationRenamer(association);
             }
         }
     }
 }
        public virtual Database Load(string databaseName, INameAliases nameAliases, NameFormat nameFormat,
            bool loadStoredProcedures, string contextNamespace, string entityNamespace)
        {
            // check if connection is open. Note: we may use something more flexible
            if (Connection.State != ConnectionState.Open)
                Connection.Open();

            // get the database name. If we don't have one, take it from connection string...
            if (string.IsNullOrEmpty(databaseName))
                databaseName = Connection.Database;
            // ... and if connection string doesn't provide a name, then throw an error
            if (string.IsNullOrEmpty(databaseName))
                throw new ArgumentException("A database name is required. Please specify /database=<databaseName>");

            var schemaName = NameFormatter.GetSchemaName(databaseName, GetExtraction(databaseName), nameFormat);
            var names = new Names();
            var schema = new Database
                             {
                                 Name = schemaName.DbName,
                                 Class = schemaName.ClassName,
                                 BaseType = typeof(DataContext).FullName,
                                 ContextNamespace = contextNamespace,
                                 EntityNamespace = entityNamespace,
                             };

            // order is important, we must have:
            // 1. tables
            // 2. columns
            // 3. constraints
            LoadTables(schema, schemaName, Connection, nameAliases, nameFormat, names);
            LoadColumns(schema, schemaName, Connection, nameAliases, nameFormat, names);
            LoadConstraints(schema, schemaName, Connection, nameFormat, names);
            if (loadStoredProcedures)
                LoadStoredProcedures(schema, schemaName, Connection, nameFormat);
            CheckNamesCaseSafety(schema);

            // check for duplicate names between properties
            CheckNames(schema);
            // generate backing fields name (since we have here correct names)
            GenerateStorageFields(schema);

            return schema;
        }
Beispiel #17
0
        protected override void LoadStoredProcedures(Database schema, SchemaName schemaName, IDbConnection conn, NameFormat nameFormat)
        {
            var procs = ReadProcedures(conn, schemaName.DbName);

            foreach (DataStoredProcedure proc in procs)
            {
                var procedureName = CreateProcedureName(proc.specific_name, proc.db, nameFormat);

                var func = new Function();
                func.Name = procedureName.DbName;
                func.Method = procedureName.MethodName;
                func.IsComposable = string.Compare(proc.type, "FUNCTION") == 0;
                func.BodyContainsSelectStatement = proc.body != null
                                                   && proc.body.IndexOf("select", StringComparison.OrdinalIgnoreCase) > -1;
                ParseProcParams(proc, func);

                schema.Functions.Add(func);
            }
        }
 protected virtual void CheckNamesCaseSafety(Database schema)
 {
     schema.Name = Vendor.SqlProvider.GetSafeName(schema.Name);
     foreach (var table in schema.Table)
     {
         table.Name = Vendor.SqlProvider.GetSafeName(table.Name);
         foreach (var column in table.Type.Columns)
         {
             column.Name = Vendor.SqlProvider.GetSafeName(column.Name);
         }
         foreach (var association in table.Type.Associations)
         {
             association.Name = Vendor.SqlProvider.GetSafeName(association.Name);
         }
     }
     foreach (var storedProcedure in schema.Functions)
     {
         storedProcedure.Name = Vendor.SqlProvider.GetSafeName(storedProcedure.Name);
     }
 }
        protected virtual CodeNamespace GenerateCodeDomModel(Database database)
        {
            CodeNamespace _namespace = new CodeNamespace(database.ContextNamespace);

            _namespace.Imports.Add(new CodeNamespaceImport("System"));
            _namespace.Imports.Add(new CodeNamespaceImport("System.ComponentModel"));
            _namespace.Imports.Add(new CodeNamespaceImport("System.Data"));
            _namespace.Imports.Add(new CodeNamespaceImport("System.Data.Linq.Mapping"));
            _namespace.Imports.Add(new CodeNamespaceImport("System.Diagnostics"));
            _namespace.Imports.Add(new CodeNamespaceImport("DbLinq.Linq"));
            _namespace.Imports.Add(new CodeNamespaceImport("DbLinq.Linq.Mapping"));

            _namespace.Comments.Add(new CodeCommentStatement(GenerateCommentBanner(database)));

            _namespace.Types.Add(GenerateContextClass(database));

            foreach (Table table in database.Tables)
                _namespace.Types.Add(GenerateTableClass(table));
            return _namespace;
        }
        protected override void LoadStoredProcedures(Database schema, SchemaName schemaName, IDbConnection conn, NameFormat nameFormat)
        {
            var procs = ReadProcedures(conn, schemaName.DbName);

            //4a. determine unknown types
            Dictionary<long, string> typeOidToName = new Dictionary<long, string>();

            foreach (DataStoredProcedure proc in procs)
            {
                if (proc.proallargtypes == null && !string.IsNullOrEmpty(proc.proargtypes))
                    proc.proallargtypes = "{" + proc.proargtypes.Replace(' ', ',') + "}"; //work around pgsql weirdness?
            }

            foreach (DataStoredProcedure proc in procs)
            {
                typeOidToName[proc.prorettype] = proc.formatted_prorettype;
                if (proc.proallargtypes == null)
                    continue; //no args, no Oids to resolve, skip

                string[] argTypes1 = parseCsvString(proc.proallargtypes); //eg. {23,24,1043}
                var argTypes2 = from t in argTypes1 select long.Parse(t);

                foreach (long argType in argTypes2)
                {
                    if (!typeOidToName.ContainsKey(argType))
                        typeOidToName[argType] = null;
                }
            }

            //4b. get names for unknown types
            GetTypeNames(conn, schemaName.DbName, typeOidToName);

            //4c. generate dbml objects
            foreach (DataStoredProcedure proc in procs)
            {
                DbLinq.Schema.Dbml.Function dbml_fct = ParseFunction(proc, typeOidToName, nameFormat);
                if (!SkipProc(dbml_fct.Name))
                    schema.Functions.Add(dbml_fct);
            }
        }
Beispiel #21
0
        protected override void LoadStoredProcedures(Database schema, SchemaName schemaName, IDbConnection conn, NameFormat nameFormat)
        {
            // TODO: debug stored procedures support
            return;

            var procs = ReadProcedures(conn, schemaName.DbName);

            foreach (DataStoredProcedure proc in procs)
            {
                var procedureName = CreateProcedureName(proc.Name, proc.TableSchema, nameFormat);

                var func = new Function();

                func.Name = procedureName.DbName;
                func.Method = procedureName.MethodName;
                func.IsComposable = string.Compare(proc.Type, "FUNCTION") == 0;
                func.BodyContainsSelectStatement = proc.BodyContainsSelectStatement;
                ParseProcParams(proc, func);

                schema.Functions.Add(func);
            }
        }
 /// <summary>
 /// Checks for problematic names on columns
 /// We currently have 1 case, where column is equal to table name
 /// </summary>
 /// <param name="schema"></param>
 protected virtual void CheckColumnsName(Database schema)
 {
     foreach (var table in schema.Tables)
     {
         foreach (var column in table.Type.Columns)
         {
             // THE case
             if (column.Member == table.Type.Name)
             {
                 // now, we try to append 1, then 2, etc.
                 var appendValue = 0;
                 for (; ; )
                 {
                     var newColumnMember = column.Member + ++appendValue;
                     if (!table.Type.Columns.Any(c => c.Member == newColumnMember))
                     {
                         column.Member = newColumnMember;
                     }
                 }
             }
         }
     }
 }
Beispiel #23
0
 /// <summary>
 /// guess which fields are populated by sequences.
 /// Mark them with [AutoGenId].
 /// </summary>
 public static void GuessSequencePopulatedFields(DbLinq.Schema.Dbml.Database schema)
 {
     if (schema == null)
     {
         return;
     }
     foreach (DbLinq.Schema.Dbml.Table tbl in schema.Tables)
     {
         var q = from col in tbl.Type.Columns
                 where col.IsPrimaryKey
                 select col;
         List <DbLinq.Schema.Dbml.Column> cols = q.ToList();
         bool canBeFromSequence = cols.Count == 1 &&
                                  (!cols[0].CanBeNull) &&
                                  (cols[0].DbType == "NUMBER" || cols[0].DbType == "INTEGER");
         if (canBeFromSequence)
         {
             //TODO: query sequences, store sequence name.
             //in the meantime, assume naming convention similar to 'Products_seq'
             cols[0].IsDbGenerated = true;
         }
     }
 }
        public void GenerateCode(Parameters parameters, Database dbSchema, ISchemaLoader schemaLoader, string filename)
        {
            ICodeGenerator codeGenerator = FindCodeGenerator(parameters, filename);
            if (codeGenerator == null)
                throw new ArgumentException("Please specify either a /language or a /code file");

            if (string.IsNullOrEmpty(filename))
                filename = dbSchema.Class;
            if (String.IsNullOrEmpty(Path.GetExtension(filename)))
                filename += codeGenerator.Extension;

            using (var streamWriter = new StreamWriter(filename))
            {
                var generationContext = new GenerationContext(parameters, schemaLoader);
                codeGenerator.Write(streamWriter, dbSchema, generationContext);
            }
        }
 protected void RemoveSchemaFromTables(Database schema)
 {
     foreach (var table in schema.Table)
     {
         string[] nameAndSchema = table.Name.Split('.');
         table.Name = nameAndSchema[nameAndSchema.Length - 1];
     }
 }
        protected void WriteSchema(Database dbSchema, ISchemaLoader schemaLoader, Parameters parameters)
        {
            if (parameters.Dbml != null)
            {
                //we are supposed to write out a DBML file and exit
                parameters.Write("<<< Writing file '{0}'", parameters.Dbml);
                using (Stream dbmlFile = File.Create(parameters.Dbml))
                {
                    DbmlSerializer.Write(dbmlFile, dbSchema);
                }
            }
            else
            {
                if (!parameters.Schema)
                    RemoveSchemaFromTables(dbSchema);

                // extract filename from output filename, database schema or schema name
                string filename = parameters.Code;
                if (string.IsNullOrEmpty(filename) && !string.IsNullOrEmpty(parameters.Database))
                    filename = parameters.Database.Replace("\"", "");
                if (string.IsNullOrEmpty(filename))
                    filename = dbSchema.Name;

                // TODO: move such check to runtime.
                schemaLoader.CheckNamesSafety(dbSchema);

                parameters.Write("<<< writing C# classes in file '{0}'", filename);
                GenerateCode(parameters, dbSchema, schemaLoader, filename);

            }
        }
 /// <summary>
 /// Writes class ctor.
 /// EntitySet initializations
 /// </summary>
 /// <param name="writer"></param>
 /// <param name="table"></param>
 /// <param name="schema"></param>
 /// <param name="context"></param>
 protected virtual void WriteClassCtor(CodeWriter writer, Table table, Database schema, GenerationContext context)
 {
     using (writer.WriteRegion("ctor"))
     using (writer.WriteCtor(SpecificationDefinition.Public, table.Type.Name, new ParameterDefinition[0], null))
     {
         // children are EntitySet
         foreach (var child in GetClassChildren(table))
         {
             // if the association has a storage, we use it. Otherwise, we use the property name
             var entitySetMember = child.Storage ?? child.Member;
             writer.WriteLine(writer.GetStatement(
                 writer.GetAssignmentExpression(
                     entitySetMember,
                     writer.GetNewExpression(writer.GetMethodCallExpression(
                         writer.GetGenericName(TypeExtensions.GetShortName(typeof(EntitySet<>)), child.Type),
                         GetChildAttachMethodName(child),
                         GetChildDetachMethodName(child)
                     ))
                 )
                 ));
         }
         // the parents are the entities referenced by a FK. So a "parent" is an EntityRef
         foreach (var parent in GetClassParents(table))
         {
             var entityRefMember = parent.Storage;
             writer.WriteLine(writer.GetStatement(
                 writer.GetAssignmentExpression(
                     entityRefMember,
                     writer.GetNewExpression(writer.GetMethodCallExpression(
                     writer.GetGenericName(TypeExtensions.GetShortName(typeof(EntityRef<>)), parent.Type)
                     ))
                 )
             ));
         }
         writer.WriteLine(writer.GetStatement(writer.GetMethodCallExpression("OnCreated")));
     }
 }
 /// <summary>
 /// Writes attach/detach method
 /// </summary>
 /// <param name="writer"></param>
 /// <param name="table"></param>
 /// <param name="schema"></param>
 /// <param name="context"></param>
 protected virtual void WriteClassChildrenAttachment(CodeWriter writer, Table table, Database schema, GenerationContext context)
 {
     var children = GetClassChildren(table).ToList();
     if (children.Count > 0)
     {
         using (writer.WriteRegion("Attachement handlers"))
         {
             foreach (var child in children)
             {
                 // the reverse child is the association seen from the child
                 // we're going to use it...
                 var reverseChild = schema.GetReverseAssociation(child);
                 // ... to get the parent name
                 var memberName = reverseChild.Member;
                 var entityParameter = new ParameterDefinition { Name = "entity", LiteralType = child.Type };
                 // the Attach event handler sets the child entity parent to "this"
                 using (writer.WriteMethod(SpecificationDefinition.Private, GetChildAttachMethodName(child),
                                           null, entityParameter))
                 {
                     writer.WriteLine(
                         writer.GetStatement(
                             writer.GetAssignmentExpression(
                                 writer.GetMemberExpression(entityParameter.Name, memberName),
                                 writer.GetThisExpression())));
                 }
                 writer.WriteLine();
                 // the Detach event handler sets the child entity parent to null
                 using (writer.WriteMethod(SpecificationDefinition.Private, GetChildDetachMethodName(child),
                                           null, entityParameter))
                 {
                     writer.WriteLine(
                         writer.GetStatement(
                             writer.GetAssignmentExpression(
                                 writer.GetMemberExpression(entityParameter.Name, memberName),
                                 writer.GetNullExpression())));
                 }
                 writer.WriteLine();
             }
         }
     }
 }
        protected virtual void WriteClassParent(CodeWriter writer, Association parent, bool hasDuplicates, Database schema, GenerationContext context)
        {
            // the following is apparently useless
            DbLinq.Schema.Dbml.Table targetTable = schema.Tables.FirstOrDefault(t => t.Type.Name == parent.Type);
            if (targetTable == null)
            {
                //Logger.Write(Level.Error, "ERROR L191 target table type not found: " + parent.Type + "  (processing " + parent.Name + ")");
                return;
            }

            string member = parent.Member;
            string storageField = parent.Storage;
            // TODO: remove this
            if (member == parent.ThisKey)
            {
                member = parent.ThisKey + targetTable.Type.Name; //repeat name to prevent collision (same as Linq)
                storageField = "_x_" + parent.Member;
            }

            writer.WriteField(SpecificationDefinition.Private, storageField,
                              writer.GetGenericName(TypeExtensions.GetShortName(typeof(EntityRef<>)),
                                                    targetTable.Type.Name));

            var storageAttribute = NewAttributeDefinition<AssociationAttribute>();
			storageAttribute["Storage"] = storageField;
			storageAttribute["OtherKey"] = parent.OtherKey;
            storageAttribute["ThisKey"] = parent.ThisKey;
            storageAttribute["Name"] = parent.Name;
            storageAttribute["IsForeignKey"] = parent.IsForeignKey;

            SpecificationDefinition specifications;
            if (parent.AccessModifierSpecified)
                specifications = GetSpecificationDefinition(parent.AccessModifier);
            else
                specifications = SpecificationDefinition.Public;
            if (parent.ModifierSpecified)
                specifications |= GetSpecificationDefinition(parent.Modifier);

            var propertyName = hasDuplicates
                                   ? member + "_" + string.Join("", parent.TheseKeys.ToArray())
                                   : member;

            using (writer.WriteAttribute(storageAttribute))
            using (writer.WriteAttribute(NewAttributeDefinition<DebuggerNonUserCodeAttribute>()))
            using (writer.WriteProperty(specifications, propertyName, targetTable.Type.Name))
            {
                string storage = writer.GetMemberExpression(storageField, "Entity");
                using (writer.WritePropertyGet())
                {
                    writer.WriteLine(writer.GetReturnStatement(storage));
                }
                using (writer.WritePropertySet())
                {
                    // algorithm is:
                    // 1.1. must be different than previous value
                    // 1.2. or HasLoadedOrAssignedValue is false (but why?)
                    // 2. implementations before change
                    // 3. if previous value not null
                    // 3.1. place parent in temp variable
                    // 3.2. set [Storage].Entity to null
                    // 3.3. remove it from parent list
                    // 4. assign value to [Storage].Entity
                    // 5. if value is not null
                    // 5.1. add it to parent list
                    // 5.2. set FK members with entity keys
                    // 6. else
                    // 6.1. set FK members to defaults (null or 0)
                    // 7. implementationas after change

                    //writer.WriteLine(writer.GetStatement(writer.GetAssignmentExpression(storage, writer.GetPropertySetValueExpression())));
                    var entityMember = writer.GetMemberExpression(parent.Storage, "Entity");
                    // 1.1
                    using (writer.WriteIf(writer.GetDifferentExpression(writer.GetPropertySetValueExpression(),
                                                                        entityMember)))
                    {
                        var otherAssociation = schema.GetReverseAssociation(parent);
                        // 2. code before the change
                        // TODO change interface to require a member instead of a column
                        //foreach (IImplementation implementation in context.Implementations())
                        //    implementation.WritePropertyBeforeSet(writer, ???, context);
                        // 3.
                        using (writer.WriteIf(writer.GetDifferentExpression(entityMember, writer.GetNullExpression())))
                        {
                            var previousEntityRefName = "previous" + parent.Type;
                            // 3.1.
                            writer.WriteLine(writer.GetStatement(
                                writer.GetVariableDeclarationInitialization(parent.Type, previousEntityRefName, entityMember)
                                ));
                            // 3.2.
                            writer.WriteLine(writer.GetStatement(
                                writer.GetAssignmentExpression(entityMember, writer.GetNullExpression())
                                ));
                            // 3.3.
                            writer.WriteLine(writer.GetStatement(
                                writer.GetMethodCallExpression(
                                    writer.GetMemberExpression(writer.GetMemberExpression(previousEntityRefName, otherAssociation.Member), "Remove"),
                                    writer.GetThisExpression())
                                ));
                        }
                        // 4.
                        writer.WriteLine(writer.GetStatement(
                            writer.GetAssignmentExpression(entityMember, writer.GetPropertySetValueExpression())
                            ));

                        // 5. if value is null or not
                        writer.WriteRawIf(writer.GetDifferentExpression(writer.GetPropertySetValueExpression(), writer.GetNullExpression()));
                        // 5.1.
                        writer.WriteLine(writer.GetStatement(
                            writer.GetMethodCallExpression(
                                writer.GetMemberExpression(writer.GetMemberExpression(writer.GetPropertySetValueExpression(), otherAssociation.Member), "Add"),
                                writer.GetThisExpression())
                            ));

                        // 5.2
                        var table = schema.Tables.Single(t => t.Type.Associations.Contains(parent));
                        var childKeys = parent.TheseKeys.ToArray();
                        var childColumns = (from ck in childKeys select table.Type.Columns.Single(c => c.Member == ck))
                                            .ToArray();
                        var parentKeys = parent.OtherKeys.ToArray();

                        for (int keyIndex = 0; keyIndex < parentKeys.Length; keyIndex++)
                        {
                            writer.WriteLine(writer.GetStatement(writer.GetAssignmentExpression(
                                childColumns[keyIndex].Storage ?? childColumns[keyIndex].Member,
                                writer.GetMemberExpression(writer.GetPropertySetValueExpression(), parentKeys[keyIndex])
                                )));
                        }

                        // 6.
                        writer.WriteRawElse();

                        // 6.1.
                        for (int keyIndex = 0; keyIndex < parentKeys.Length; keyIndex++)
                        {
                            var column = table.Type.Columns.Single(c => c.Member == childKeys[keyIndex]);
                            var columnType = System.Type.GetType(column.Type);
                            var columnLiteralType = columnType != null ? writer.GetLiteralType(columnType) : column.Type;
                            writer.WriteLine(writer.GetStatement(writer.GetAssignmentExpression(
                                childColumns[keyIndex].Storage ?? childColumns[keyIndex].Member,
                                column.CanBeNull ? writer.GetNullExpression() : writer.GetNullValueExpression(columnLiteralType)
                                )));
                        }

                        writer.WriteRawEndif();

                        // 7. code after change
                        // TODO change interface to require a member instead of a column
                        //foreach (IImplementation implementation in context.Implementations())
                        //    implementation.WritePropertyAfterSet(writer, ???, context);

                    }
                }
            }
            writer.WriteLine();
        }
 protected virtual void WriteClassParents(CodeWriter writer, Table table, Database schema, GenerationContext context)
 {
     var parents = GetClassParents(table).ToList();
     if (parents.Count > 0)
     {
         using (writer.WriteRegion("Parents"))
         {
             foreach (var parent in parents)
             {
                 bool hasDuplicates = (from p in parents where p.Member == parent.Member select p).Count() > 1;
                 WriteClassParent(writer, parent, hasDuplicates, schema, context);
             }
         }
     }
 }
        private void WriteClassChild(CodeWriter writer, Association child, bool hasDuplicates, Database schema, GenerationContext context)
        {
            // the following is apparently useless
            DbLinq.Schema.Dbml.Table targetTable = schema.Tables.FirstOrDefault(t => t.Type.Name == child.Type);
            if (targetTable == null)
            {
                //Logger.Write(Level.Error, "ERROR L143 target table class not found:" + child.Type);
                return;
            }

            var storageAttribute = NewAttributeDefinition<AssociationAttribute>();
            storageAttribute["Storage"] = child.Storage;
            storageAttribute["OtherKey"] = child.OtherKey;
            storageAttribute["ThisKey"] = child.ThisKey;
            storageAttribute["Name"] = child.Name;

            SpecificationDefinition specifications;
            if (child.AccessModifierSpecified)
                specifications = GetSpecificationDefinition(child.AccessModifier);
            else
                specifications = SpecificationDefinition.Public;
            if (child.ModifierSpecified)
                specifications |= GetSpecificationDefinition(child.Modifier);

            var propertyName = hasDuplicates
                                   ? child.Member + "_" + string.Join("", child.OtherKeys.ToArray())
                                   : child.Member;

            var propertyType = writer.GetGenericName(TypeExtensions.GetShortName(typeof(EntitySet<>)), child.Type);

            if (child.Storage != null)
                writer.WriteField(SpecificationDefinition.Private, child.Storage, propertyType);

            using (writer.WriteAttribute(storageAttribute))
            using (writer.WriteAttribute(NewAttributeDefinition<DebuggerNonUserCodeAttribute>()))
            using (writer.WriteProperty(specifications, propertyName,
                                        writer.GetGenericName(TypeExtensions.GetShortName(typeof(EntitySet<>)), child.Type)))
            {
                // if we have a backing field, use it
                if (child.Storage != null)
                {
                    // the getter returns the field
                    using (writer.WritePropertyGet())
                    {
                        writer.WriteLine(writer.GetReturnStatement(
                            child.Storage
                            ));
                    }
                    // the setter assigns the field
                    using (writer.WritePropertySet())
                    {
                        writer.WriteLine(writer.GetStatement(
                            writer.GetAssignmentExpression(
                            child.Storage,
                            writer.GetPropertySetValueExpression())
                            ));
                    }
                }
                // otherwise, use automatic property
                else
                    writer.WriteAutomaticPropertyGetSet();
            }
            writer.WriteLine();
        }
 protected virtual void WriteClassChildren(CodeWriter writer, Table table, Database schema, GenerationContext context)
 {
     var children = GetClassChildren(table).ToList();
     if (children.Count > 0)
     {
         using (writer.WriteRegion("Children"))
         {
             foreach (var child in children)
             {
                 bool hasDuplicates = (from c in children where c.Member == child.Member select c).Count() > 1;
                 WriteClassChild(writer, child, hasDuplicates, schema, context);
             }
         }
     }
 }