EF Core 3.1 Fluent API не обнаруживает изменения объекта - PullRequest
0 голосов
/ 20 апреля 2020

Я использую EF Core 3.1 с плавным API и настраиваю сущности в определенном c объектах карты, как показано ниже:

public class CouponMap: IEntityTypeConfiguration < Coupon > {
    public void Configure(EntityTypeBuilder < Coupon > builder) {
        builder.HasKey(t = >t.Id);
        builder.Property(t = >t.Id).ValueGeneratedOnAdd();
        builder.Property(e = >e.Name).HasMaxLength(120).IsRequired();
        builder.Property(e = >e.Code).HasMaxLength(120).IsRequired();
        builder.Property(e = >e.Value).HasColumnType("decimal(19,4)").IsRequired();

        // Relations...
        builder.HasOne < AppUser > (e = >e.CreatedByUser).WithMany().HasForeignKey(e = >e.DeletedBy).IsRequired();
        builder.HasOne < AppUser > (e = >e.DeletedByUser).WithMany().HasForeignKey(e = >e.CreatedBy).IsRequired();
        builder.HasOne < AppUser > (e = >e.UpdatedByUser).WithMany().HasForeignKey(e = >e.UpdatedBy);

        // Set table name
        builder.ToTable("Coupon", "dbo");
    }
}

Затем я заметил на консоли отладки, что есть предупреждения для моих десятичных полей такие как:

Microsoft.EntityFrameworkCore.Model.Validation[30000] No type was specified for the decimal column 'Value' on entity type 'Coupon'. This will cause values to be silently truncated if they do not fit in the default precision and scale. Explicitly specify the SQL server column type that can accommodate all the values using 'HasColumnType()'.

Но я фактически уже определил, что HasColumnType в моем объекте карты, как вы можете видеть выше. Сначала я подумал, что это может быть просто предупреждением, потому что он не может обнаружить изменения «как-то», но когда я проверял свою таблицу в БД, я увидел, что столбец «Значение таблицы купонов» фактически использует значение по умолчанию (18,2) в качестве десятичной шкалы точности не ( 19,4).

Объект купона. Значение поля определяется следующим образом:

public class Coupon : IHasIdColumn<int>
    {         
        public int Id { get; set; }
        public string Name { get; set; }
        .
        .
        .      
        public decimal Value { get; set; } // <== the problem guy!
        .
        .           
   }

enter image description here

Также, если вы заметили, поля Код и Имя были четными создается как NVARCHAR(MAX) событие, хотя они установлены как HasMaxLength(120) в объекте карты.

После этого я проверяю снимок моей модели, чтобы убедиться, что мой сценарий сущности генерируется только для подтверждения того, что он проигнорировал мой десятичный код (19, 4) и подтвердил, что он фактически создал сценарий таблицы в снимке модели следующим образом:

modelBuilder.Entity("MyProject.Core.DomainModels.Coupon", b = >{
    b.Property < int > ("Id").ValueGeneratedOnAdd().HasColumnType("int").HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
    .
    .
    b.Property < decimal > ("Value").HasColumnType("decimal(18,2)");
    .  
    .
    . goes with other properties
}

Тогда я понял, что попытался обновить другие свойства в моем объекте CouponMap, но ни одно из этих изменений был обнаружен. Например, я попытался изменить максимальную длину одного столбца со 120 до 500, как показано ниже, и добавить новую миграцию, но мои функции up и down были пусты.

public class CouponMap: IEntityTypeConfiguration < Coupon > {
    public void Configure(EntityTypeBuilder < Coupon > builder) {
        builder.HasKey(t = >t.Id);
        builder.Property(t = >t.Id).ValueGeneratedOnAdd();
        builder.Property(e = >e.Name).HasMaxLength(500).IsRequired(); // changed this but not detected in migration...
        builder.Property(e = >e.Code).HasMaxLength(500).IsRequired(); // also changed this but not detectedin migration...
        builder.Property(e = >e.Value).HasColumnType("decimal(19,4)").IsRequired(); // this somehow was not being detected anyways so I tried other 2 columns above

        // Relations...
        builder.HasOne < AppUser > (e = >e.CreatedByUser).WithMany().HasForeignKey(e = >e.DeletedBy).IsRequired();
        builder.HasOne < AppUser > (e = >e.DeletedByUser).WithMany().HasForeignKey(e = >e.CreatedBy).IsRequired();
        builder.HasOne < AppUser > (e = >e.UpdatedByUser).WithMany().HasForeignKey(e = >e.UpdatedBy);

        // Set table name
        builder.ToTable("Coupon", "dbo");
    }
}

Я знаю, что могу использовать System.ComponentModel.DataAnnotations.Schema и украсить мою собственность, как показано ниже:

[Column(TypeName = "decimal(19,4)")]
public decimal Value { get; set; }

Если я сделаю это и создам новую миграцию, я вижу, что она сразу же обнаруживает изменение, и мои функции up и down выглядят следующим образом:

 protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.AlterColumn<decimal>(
        name: "Value",
        table: "Coupon",
        type: "decimal(19,4)",
        nullable: false,
        oldClrType: typeof(decimal),
        oldType: "decimal(18,2)");
}

protected override void Down(MigrationBuilder migrationBuilder)
{
    migrationBuilder.AlterColumn<decimal>(
        name: "Value",
        table: "Coupon",
        type: "decimal(18,2)",
        nullable: false,
        oldClrType: typeof(decimal),
        oldType: "decimal(19,4)");
}

Но я хочу сохранить свои доменные объекты как можно более чистыми и использовать только EntityMap классы для определения любой конфигурации типа сущности, связанной с базой данных (в противном случае, какой смысл использовать FluentAPI?)

Я думал, что, может быть, объекты моей карты сущностей бесполезны, но отношения, которые я создал в объектах карты сущностей, работают отлично.

Я пытался очистить решение, перестроить, перезапустить VS, но ни один из них не сработал. Любое предложение или я что-то здесь упускаю?

1 Ответ

0 голосов
/ 21 апреля 2020

Проблема заключалась в том, что эти объекты сопоставления не вызывались вообще.

Решение было простым:

protected override void OnModelCreating(ModelBuilder builder)
        { 
            // configuring mappings one by one like below..
            //  builder.ApplyConfiguration(new CouponMap());
            //  builder.ApplyConfiguration(new WebOrderMap());

            // or configuring all the mappings by using assembly..
            builder.ApplyConfigurationsFromAssembly(typeof(CouponMap).Assembly);

            base.OnModelCreating(builder);
        } 

Благодаря @Ivan Stoev, который указал мне, чтобы я выдал исключение в этих объектах отображения, чтобы посмотреть, будут ли они когда-либо срабатывать ... Это обмануло меня, потому что все мои отношения были в полном порядке, поэтому я подумал, что из-за того, что мои объекты отображения работали нормально Но на самом деле это было только из-за соглашений EF, и мои сопоставления объектов никогда не запускались.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...