Example #1
0
        public void Unmappable_column_type(string StoreType)
        {
            var info = new DatabaseModel
            {
                Tables =
                {
                    new DatabaseTable
                    {
                        Name       = "E",
                        Columns    = { IdColumn },
                        PrimaryKey = IdPrimaryKey
                    }
                }
            };

            info.Tables.First()
            .Columns.Add(
                new DatabaseColumn
            {
                Table     = info.Tables.First(),
                Name      = "Coli",
                StoreType = StoreType
            });

            Assert.Single(_factory.Create(info).FindEntityType("E").GetProperties());
            Assert.Single(_reporter.Messages, t => t.Contains(DesignStrings.CannotFindTypeMappingForColumn("E.Coli", StoreType)));
        }
        public void E2ETest_UseAttributesInsteadOfFluentApi()
        {
            var filePaths = Generator.Generate(
                _connectionString,
                Tables,
                Enumerable.Empty <string>(),
                TestProjectDir + Path.DirectorySeparatorChar,     // tests that ending DirectorySeparatorChar does not affect namespace
                TestSubDir,
                TestNamespace,
                contextName: "AttributesContext",
                useDataAnnotations: true,
                overwriteFiles: false,
                useDatabaseNames: false);

            var actualFileSet = new FileSet(InMemoryFiles, Path.GetFullPath(Path.Combine(TestProjectDir, TestSubDir)))
            {
                Files = Enumerable.Repeat(filePaths.ContextFile, 1).Concat(filePaths.EntityTypeFiles).Select(Path.GetFileName).ToList()
            };

            var expectedFileSet = new FileSet(new FileSystemFileService(),
                                              Path.Combine("ReverseEngineering", "Expected", "Attributes"),
                                              contents => contents.Replace("{{connectionString}}", _connectionString))
            {
                Files = new List <string> {
                    "AttributesContext.cs"
                }
                .Concat(_expectedEntityTypeFiles).ToList()
            };

            Assert.Contains(_reporter.Messages, m => m.StartsWith("warn: ") && m.Contains("PK__Filtered__"));
            Assert.Contains("warn: " + DesignStrings.CannotFindTypeMappingForColumn("dbo.AllDataTypes.geographyColumn", "geography"), _reporter.Messages);
            Assert.Contains("warn: " + DesignStrings.CannotFindTypeMappingForColumn("dbo.AllDataTypes.geometryColumn", "geometry"), _reporter.Messages);
            Assert.Contains("warn: " + DesignStrings.CannotFindTypeMappingForColumn("dbo.AllDataTypes.hierarchyidColumn", "hierarchyid"), _reporter.Messages);
            Assert.Contains("warn: " + DesignStrings.CannotFindTypeMappingForColumn("dbo.AllDataTypes.sql_variantColumn", "sql_variant"), _reporter.Messages);
            Assert.Contains("warn: " + DesignStrings.UnableToScaffoldIndexMissingProperty("IX_UnscaffoldableIndex", "sql_variantColumn,hierarchyidColumn"), _reporter.Messages);
            Assert.Contains("warn: " + DesignStrings.CannotFindTypeMappingForColumn("dbo.TableWithUnmappablePrimaryKeyColumn.TableWithUnmappablePrimaryKeyColumnID", "hierarchyid"), _reporter.Messages);
            Assert.Contains("warn: " + DesignStrings.PrimaryKeyErrorPropertyNotFound("dbo.TableWithUnmappablePrimaryKeyColumn", "TableWithUnmappablePrimaryKeyColumnID"), _reporter.Messages);
            Assert.Contains("warn: " + DesignStrings.UnableToGenerateEntityType("dbo.TableWithUnmappablePrimaryKeyColumn"), _reporter.Messages);
            Assert.Equal(9, _reporter.Messages.Count(m => m.StartsWith("warn: ")));
            AssertEqualFileContents(expectedFileSet, actualFileSet);
            AssertCompile(actualFileSet);
        }
        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        protected virtual PropertyBuilder VisitColumn([NotNull] EntityTypeBuilder builder, [NotNull] DatabaseColumn column)
        {
            Check.NotNull(builder, nameof(builder));
            Check.NotNull(column, nameof(column));

            var typeScaffoldingInfo = GetTypeScaffoldingInfo(column);

            if (typeScaffoldingInfo == null)
            {
                _unmappedColumns.Add(column);
                _reporter.WriteWarning(
                    DesignStrings.CannotFindTypeMappingForColumn(column.DisplayName(), column.StoreType));
                return(null);
            }

            var clrType = typeScaffoldingInfo.ClrType;

            if (column.IsNullable)
            {
                clrType = clrType.MakeNullable();
            }

            if (clrType == typeof(bool) &&
                column.DefaultValueSql != null)
            {
                _reporter.WriteWarning(
                    DesignStrings.NonNullableBoooleanColumnHasDefaultConstraint(column.DisplayName()));

                clrType = clrType.MakeNullable();
            }

            var property = builder.Property(clrType, GetPropertyName(column));

            property.HasColumnName(column.Name);

            if (!typeScaffoldingInfo.IsInferred &&
                !string.IsNullOrWhiteSpace(column.StoreType))
            {
                property.HasColumnType(column.StoreType);
            }

            if (typeScaffoldingInfo.ScaffoldUnicode.HasValue)
            {
                property.IsUnicode(typeScaffoldingInfo.ScaffoldUnicode.Value);
            }

            if (typeScaffoldingInfo.ScaffoldFixedLength == true)
            {
                property.IsFixedLength();
            }

            if (typeScaffoldingInfo.ScaffoldMaxLength.HasValue)
            {
                property.HasMaxLength(typeScaffoldingInfo.ScaffoldMaxLength.Value);
            }

            if (typeScaffoldingInfo.ScaffoldPrecision.HasValue)
            {
                if (typeScaffoldingInfo.ScaffoldScale.HasValue)
                {
                    property.HasPrecision(
                        typeScaffoldingInfo.ScaffoldPrecision.Value,
                        typeScaffoldingInfo.ScaffoldScale.Value);
                }
                else
                {
                    property.HasPrecision(typeScaffoldingInfo.ScaffoldPrecision.Value);
                }
            }

            if (column.ValueGenerated == ValueGenerated.OnAdd)
            {
                property.ValueGeneratedOnAdd();
            }

            if (column.ValueGenerated == ValueGenerated.OnUpdate)
            {
                property.ValueGeneratedOnUpdate();
            }

            if (column.ValueGenerated == ValueGenerated.OnAddOrUpdate)
            {
                property.ValueGeneratedOnAddOrUpdate();
            }

            if (column.DefaultValueSql != null)
            {
                property.HasDefaultValueSql(column.DefaultValueSql);
            }

            if (column.ComputedColumnSql != null)
            {
                property.HasComputedColumnSql(column.ComputedColumnSql, column.ComputedColumnIsStored);
            }

            if (column.Comment != null)
            {
                property.HasComment(column.Comment);
            }

            if (column.Collation != null)
            {
                property.HasComment(column.Collation);
            }

            if (!(column.Table.PrimaryKey?.Columns.Contains(column) ?? false))
            {
                property.IsRequired(!column.IsNullable);
            }

            if ((bool?)column[ScaffoldingAnnotationNames.ConcurrencyToken] == true)
            {
                property.IsConcurrencyToken();
            }

            property.Metadata.SetColumnOrdinal(column.Table.Columns.IndexOf(column));

            property.Metadata.AddAnnotations(
                column.GetAnnotations().Where(
                    a => a.Name != ScaffoldingAnnotationNames.ConcurrencyToken));

            return(property);
        }
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        protected virtual PropertyBuilder VisitColumn(EntityTypeBuilder builder, DatabaseColumn column)
        {
            if (builder == null)
            {
                throw new ArgumentNullException(nameof(builder));
            }
            if (column == null)
            {
                throw new ArgumentNullException(nameof(column));
            }

            var typeScaffoldingInfo = GetTypeScaffoldingInfo(column);

            if (typeScaffoldingInfo == null)
            {
                _unmappedColumns.Add(column);
                _reporter.WriteWarning(
                    DesignStrings.CannotFindTypeMappingForColumn(column.DisplayName(), column.StoreType));
                return(null);
            }

            var clrType       = typeScaffoldingInfo.ClrType;
            var forceNullable = typeof(bool) == clrType && column.DefaultValueSql != null;

            if (forceNullable)
            {
                _reporter.WriteWarning(
                    DesignStrings.NonNullableBoooleanColumnHasDefaultConstraint(column.DisplayName()));
            }
            if (column.IsNullable || forceNullable)
            {
                clrType = clrType.MakeNullable();
            }

            var property = builder.Property(clrType, GetPropertyName(column));

            property.HasColumnName(column.Name);

            if (!typeScaffoldingInfo.IsInferred &&
                !string.IsNullOrWhiteSpace(column.StoreType))
            {
                property.HasColumnType(column.StoreType);
            }

            if (typeScaffoldingInfo.ScaffoldUnicode.HasValue)
            {
                property.IsUnicode(typeScaffoldingInfo.ScaffoldUnicode.Value);
            }

            if (typeScaffoldingInfo.ScaffoldMaxLength.HasValue)
            {
                property.HasMaxLength(typeScaffoldingInfo.ScaffoldMaxLength.Value);
            }

            if (column.ValueGenerated == ValueGenerated.OnAdd)
            {
                property.ValueGeneratedOnAdd();
            }

            if (column.ValueGenerated == ValueGenerated.OnUpdate)
            {
                property.ValueGeneratedOnUpdate();
            }

            if (column.ValueGenerated == ValueGenerated.OnAddOrUpdate)
            {
                property.ValueGeneratedOnAddOrUpdate();
            }

            if (column.DefaultValueSql != null)
            {
                property.HasDefaultValueSql(column.DefaultValueSql);
            }

            if (column.ComputedColumnSql != null)
            {
                property.HasComputedColumnSql(column.ComputedColumnSql);
            }

            if (!(column.Table.PrimaryKey?.Columns.Contains(column) ?? false))
            {
                property.IsRequired(!column.IsNullable && !forceNullable);
            }

            if ((bool?)column[ScaffoldingAnnotationNames.ConcurrencyToken] == true)
            {
                property.IsConcurrencyToken();
            }

            property.Metadata.Scaffolding().ColumnOrdinal = column.Table.Columns.IndexOf(column);

            property.Metadata.AddAnnotations(
                column.GetAnnotations().Where(
                    a => a.Name != ScaffoldingAnnotationNames.UnderlyingStoreType &&
                    a.Name != ScaffoldingAnnotationNames.ConcurrencyToken));

            return(property);
        }