예제 #1
0
        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);
                }
            }
        }
예제 #2
0
        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.ColumnName);
                    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 => c.Name == constraint.ColumnName).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.ColumnName, constraint.TableName, constraint.TableSchema,
                                   referencedConstraint.ColumnName, referencedConstraint.TableName,
                                   referencedConstraint.TableSchema,
                                   constraint.ConstraintName, nameFormat, names);
                }
                // custom type, this is a trigger
                else if (constraint.ConstraintType == "T" && constraint.ColumnName != null)
                {
                    var column = table.Type.Columns.Where(c => c.Name == constraint.ColumnName).First();
                    column.Expression    = constraint.Expression;
                    column.IsDbGenerated = true;
                }
            }

            //GuessSequencePopulatedFields(schema);
        }
예제 #3
0
        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);
                }
            }
        }
예제 #4
0
        protected override void LoadConstraints(Database schema, SchemaName schemaName, IDbConnection conn, NameFormat nameFormat, Names names)
        {
            foreach (var table in schema.Table)
            {
                table.Name = table.Name.Split('.').Last();
            }

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

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

            // Deal with non existing foreign key database
            if (constraints != null)
            {
                foreach (DataConstraint keyColRow in constraints)
                {
                    //find my table:
                    string tableFullDbName         = keyColRow.TableName;// GetFullDbName(keyColRow.TableName, keyColRow.TableSchema);
                    DbLinq.Schema.Dbml.Table table = schema.Tables.FirstOrDefault(t => tableFullDbName == t.Name);
                    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);
                    }
                    else
                    {
                        //A) add primary key
                        DbLinq.Schema.Dbml.Column primaryKeyCol = table.Type.Columns.First(c => c.Name == keyColRow.ColumnName);
                        primaryKeyCol.IsPrimaryKey = true;
                    }
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Writes property setter, for FK properties
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="property"></param>
        /// <param name="relatedAssociations"></param>
        /// <param name="context"></param>
        private void WriteClassPropertyAccessorSet(CodeWriter writer, Column property, IEnumerable<Association> relatedAssociations, GenerationContext context)
        {
            // if new value if different from old one
            using (writer.WriteIf(writer.GetDifferentExpression(writer.GetPropertySetValueExpression(),
                                                                writer.GetVariableExpression(property.Storage))))
            {
                // if the property is used as a FK, we ensure that it hasn't been already loaded or assigned
                foreach (var relatedAssociation in relatedAssociations)
                {
                    // first thing to check: ensure the association backend isn't already affected.
                    // if it is the case, then the property must not be manually set

                    // R# considers the following as an error, but the csc doesn't
                    //var memberName = ReflectionUtility.GetMemberInfo<DbLinq.Data.Linq.EntityRef<object>>(e => e.HasLoadedOrAssignedValue).Name;
                    var memberName = "HasLoadedOrAssignedValue";
                    using (writer.WriteIf(writer.GetMemberExpression(relatedAssociation.Storage, memberName)))
                    {
                        writer.WriteLine(writer.GetThrowStatement(writer.GetNewExpression(
                                                                      writer.GetMethodCallExpression(
                                                                          writer.GetLiteralFullType(
                                                                              typeof(
                                                                                  System.Data.Linq.
                                                                                  ForeignKeyReferenceAlreadyHasValueException
                                                                                  )))
                                                                      )));
                    }
                }
                // the before and after are used by extensions related to interfaces
                // for example INotifyPropertyChanged
                // here the code before the change
                foreach (IImplementation implementation in context.Implementations())
                    implementation.WritePropertyBeforeSet(writer, property, context);
                // property assignment
                writer.WriteLine(
                    writer.GetStatement(
                        writer.GetAssignmentExpression(writer.GetVariableExpression(property.Storage),
                                                       writer.GetPropertySetValueExpression())));
                // here the code after change
                foreach (IImplementation implementation in context.Implementations())
                    implementation.WritePropertyAfterSet(writer, property, context);
            }
        }
예제 #6
0
        /// <summary>
        /// Writes property accessor
        /// </summary>
        /// <param name="writer"></param>
        /// <param name="property"></param>
        /// <param name="relatedAssociations"></param>
        /// <param name="context"></param>
        protected virtual void WriteClassPropertyAccessors(CodeWriter writer, Column property, IEnumerable<Association> relatedAssociations, GenerationContext context)
        {
            //generate [Column(...)] attribute
            var column = NewAttributeDefinition<ColumnAttribute>();
            column["Storage"] = property.Storage;
            column["Name"] = property.Name;
            column["DbType"] = property.DbType;
            // be smart: we only write attributes when they differ from the default values
            var columnAttribute = new ColumnAttribute();
            if (property.IsPrimaryKey != columnAttribute.IsPrimaryKey)
                column["IsPrimaryKey"] = property.IsPrimaryKey;
            if (property.IsDbGenerated != columnAttribute.IsDbGenerated)
                column["IsDbGenerated"] = property.IsDbGenerated;
            if (property.AutoSync != DbLinq.Schema.Dbml.AutoSync.Default)
                column["AutoSync"] = new EnumFullname("AutoSync", property.AutoSync);
            if (property.CanBeNull != columnAttribute.CanBeNull)
                column["CanBeNull"] = property.CanBeNull;
            if (property.Expression != null)
                column["Expression"] = property.Expression;

            var specifications = property.AccessModifierSpecified
                                     ? GetSpecificationDefinition(property.AccessModifier)
                                     : SpecificationDefinition.Public;
            if (property.ModifierSpecified)
                specifications |= GetSpecificationDefinition(property.Modifier);

            //using (WriteAttributes(writer, context.Parameters.MemberExposedAttributes))
            using (WriteAttributes(writer, GetAttributeNames(context, context.Parameters.MemberAttributes)))
            using (writer.WriteAttribute(NewAttributeDefinition<DebuggerNonUserCodeAttribute>()))
            using (writer.WriteAttribute(column))
            using (writer.WriteProperty(specifications, property.Member, GetTypeOrExtendedType(writer, property)))
            {
                // on auto storage, we're just lazy
                if (property.Storage == null)
                    writer.WriteAutomaticPropertyGetSet();
                else
                {
                    using (writer.WritePropertyGet())
                    {
                        writer.WriteLine(writer.GetReturnStatement(writer.GetVariableExpression(property.Storage)));
                    }
                    using (writer.WritePropertySet())
                    {
                        WriteClassPropertyAccessorSet(writer, property, relatedAssociations, context);
                    }
                }
            }
        }
예제 #7
0
 protected virtual void WriteClassPropertyBackingField(CodeWriter writer, Column property, GenerationContext context)
 {
     //AttributeDefinition autoGenAttribute = null;
     //if (property.IsDbGenerated)
     //    autoGenAttribute = NewAttributeDefinition<AutoGenIdAttribute>();
     //using (writer.WriteAttribute(autoGenAttribute))
     // for auto-properties, we just won't generate a private field
     if (property.Storage != null)
         writer.WriteField(SpecificationDefinition.Private, property.Storage, GetTypeOrExtendedType(writer, property));
 }
예제 #8
0
 /// <summary>
 /// Writes class property
 /// </summary>
 /// <param name="writer"></param>
 /// <param name="property"></param>
 /// <param name="relatedAssociations">non null if property is a FK</param>
 /// <param name="context"></param>
 protected virtual void WriteClassProperty(CodeWriter writer, Column property, IEnumerable<Association> relatedAssociations, GenerationContext context)
 {
     using (writer.WriteRegion(string.Format("{0} {1}", GetTypeOrExtendedType(writer, property), property.Member)))
     {
         WriteClassPropertyBackingField(writer, property, context);
         WriteClassPropertyAccessors(writer, property, relatedAssociations, context);
     }
 }
예제 #9
0
 protected virtual string GetTypeOrExtendedType(CodeWriter writer, Column property)
 {
     object extendedType = property.ExtendedType;
     var enumType = extendedType as EnumType;
     if (enumType != null)
         return writer.GetEnumType(enumType.Name);
     return writer.GetLiteralType(GetType(property.Type, property.CanBeNull));
 }
예제 #10
0
        /// <summary>
        /// Loads the columns.
        /// </summary>
        /// <param name="schema">The schema.</param>
        /// <param name="schemaName">Name of the schema.</param>
        /// <param name="conn">The conn.</param>
        /// <param name="nameAliases">The name aliases.</param>
        /// <param name="nameFormat">The name format.</param>
        /// <param name="names">The names.</param>
        protected void LoadColumns(Database schema, SchemaName schemaName, IDbConnection conn, INameAliases nameAliases, NameFormat nameFormat, Names names)
        {
            var columnRows = ReadColumns(conn, schemaName.DbName);
            foreach (var columnRow in columnRows)
            {
                var columnName = CreateColumnName(columnRow.ColumnName, columnRow.TableName, columnRow.TableSchema, nameAliases, nameFormat);
                names.AddColumn(columnRow.TableName, columnName);

                //find which table this column belongs to
                string fullColumnDbName = GetFullDbName(columnRow.TableName, columnRow.TableSchema);
                DbLinq.Schema.Dbml.Table tableSchema = schema.Tables.FirstOrDefault(tblSchema => fullColumnDbName == tblSchema.Name);
                if (tableSchema == null)
                {
                    WriteErrorLine("ERROR L46: Table '" + columnRow.TableName + "' not found for column " + columnRow.ColumnName);
                    continue;
                }
                var column = new Column();
                column.Name = columnName.DbName;
                column.Member = columnName.PropertyName;
                column.DbType = columnRow.FullType;

                if (columnRow.PrimaryKey.HasValue)
                    column.IsPrimaryKey = columnRow.PrimaryKey.Value;

                bool? generated = (nameAliases != null) ? nameAliases.GetColumnGenerated(columnRow.ColumnName, columnRow.TableName, columnRow.TableSchema) : null;
                if (!generated.HasValue)
                    generated = columnRow.Generated;
                if (generated.HasValue)
                    column.IsDbGenerated = generated.Value;

                AutoSync? autoSync = (nameAliases != null) ? nameAliases.GetColumnAutoSync(columnRow.ColumnName, columnRow.TableName, columnRow.TableSchema) : null;
                if (autoSync.HasValue)
                    column.AutoSync = autoSync.Value;

                // the Expression can originate from two sources:
                // 1. DefaultValue
                // 2. Expression
                // we use any valid source (we can't have both)
                if (column.IsDbGenerated && columnRow.DefaultValue != null)
                    column.Expression = columnRow.DefaultValue;

                column.CanBeNull = columnRow.Nullable;

                string columnTypeAlias = nameAliases != null ? nameAliases.GetColumnForcedType(columnRow.ColumnName, columnRow.TableName, columnRow.TableSchema) : null;
                var columnType = MapDbType(columnName.DbName, columnRow);

                var columnEnumType = columnType as EnumType;
                if (columnEnumType != null)
                {
                    var enumType = column.SetExtendedTypeAsEnumType();
                    enumType.Name = columnEnumType.Name;
                    foreach (KeyValuePair<string, int> enumValue in columnEnumType.EnumValues)
                    {
                        enumType[enumValue.Key] = enumValue.Value;
                    }
                }
                else if (columnTypeAlias != null)
                    column.Type = columnTypeAlias;
                else
                    column.Type = columnType.ToString();

                tableSchema.Type.Columns.Add(column);
            }
        }
예제 #11
0
 static string GetStorageFieldName(Column column)
 {
     return GetStorageFieldName(column.Storage ?? column.Member);
 }
예제 #12
0
 static CodeTypeReference ToCodeTypeReference(Column column)
 {
     var t = System.Type.GetType(column.Type);
     if (t == null)
         return new CodeTypeReference(column.Type);
     return t.IsValueType && column.CanBeNull
         ? new CodeTypeReference("System.Nullable", new CodeTypeReference(column.Type))
         : new CodeTypeReference(column.Type);
 }
예제 #13
0
 CodeTypeMember CreateChangingMethodDecl(Column column)
 {
     return CreatePartialMethod(GetChangingMethodName(column.Member),
             new CodeParameterDeclarationExpression(ToCodeTypeReference(column), "value"));
 }
예제 #14
0
 CodeTypeMember CreateChangedMethodDecl(Column column)
 {
     return CreatePartialMethod(GetChangedMethodName(column.Member));
 }