C# EF Core 3.1 Fluent API未检测到实体上的更改

C# EF Core 3.1 Fluent API未检测到实体上的更改,c#,.net-core,entity-framework-core,code-first,ef-fluent-api,C#,.net Core,Entity Framework Core,Code First,Ef Fluent Api,我正在使用EF Core 3.1和fluent API,并在特定地图对象中配置实体,如下所示: public class CouponMap: IEntityTypeConfiguration < Coupon > { public void Configure(EntityTypeBuilder < Coupon > builder) { builder.HasKey(t = >t.Id); builder.Property

我正在使用EF Core 3.1和fluent API,并在特定地图对象中配置实体,如下所示:

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");
    }
}
public class Coupon : IHasIdColumn<int>
    {         
        public int Id { get; set; }
        public string Name { get; set; }
        .
        .
        .      
        public decimal Value { get; set; } // <== the problem guy!
        .
        .           
   }
[Column(TypeName = "decimal(19,4)")]
public decimal Value { get; set; }
 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)");
}

另外,如果您注意到,代码和名称字段甚至被创建为NVARCHAR(MAX)event,尽管它们在map object中设置为HasMaxLength(120)

之后,我检查我的模型快照,以确保实体脚本是如何生成的,只是为了确认它忽略了我的十进制数(19,4),并确认它确实在模型snaphot中创建了表脚本,如下所示:

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
}
我知道我可以使用
System.ComponentModel.DataAnnotations.Schema
装饰我的属性,如下所示:

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");
    }
}
public class Coupon : IHasIdColumn<int>
    {         
        public int Id { get; set; }
        public string Name { get; set; }
        .
        .
        .      
        public decimal Value { get; set; } // <== the problem guy!
        .
        .           
   }
[Column(TypeName = "decimal(19,4)")]
public decimal Value { get; set; }
 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)");
}
如果我这样做并创建新的迁移,我会看到它立即检测到更改,我的
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(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");
    }
}
public class Coupon : IHasIdColumn<int>
    {         
        public int Id { get; set; }
        public string Name { get; set; }
        .
        .
        .      
        public decimal Value { get; set; } // <== the problem guy!
        .
        .           
   }
[Column(TypeName = "decimal(19,4)")]
public decimal Value { get; set; }
 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)");
}
protected override void Up(MigrationBuilder MigrationBuilder)
{
migrationBuilder.AlterColumn(
名称:“值”,
表:“优惠券”,
类型:“十进制(19,4)”,
可为空:false,
oldClrType:typeof(十进制),
旧式:“十进制(18,2)”;
}
受保护的覆盖无效关闭(MigrationBuilder MigrationBuilder)
{
migrationBuilder.AlterColumn(
名称:“值”,
表:“优惠券”,
类型:“十进制(18,2)”,
可为空:false,
oldClrType:typeof(十进制),
旧式:“十进制(19,4)”;
}
但我希望保持域对象尽可能干净,并且只使用
EntityMap
类来定义与数据库相关的任何实体类型配置(否则使用FluentAPI有什么意义?)

我在想也许我的实体映射对象没用,但是我在实体映射对象中创建的关系工作得非常好


我尝试过清理解决方案、重建、重新启动VS,但都没有成功。有什么建议或者我遗漏了什么吗?

问题是,根本没有调用那些映射对象配置函数

解决方案很简单:

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约定和我的对象映射从未运行。

问题是,根本没有调用那些映射对象配置函数

解决方案很简单:

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约定和我的对象映射从未运行。

很可能未执行
CouponMap.Configure
中的代码。@IvanStoev-这就是我的想法,但我的所有关系都工作正常(也在CouponMap.Configure中定义)。好吧,
ValueGeneratedOnAdd
,关系-所有这些都可以在没有流畅配置的情况下工作,因为它们符合EF核心约定。为了便于测试,请注释掉
Configure
方法的内容。或者添加类似于抛出新异常(“废话”)的内容里面。@IvanStoev-你说得对。谢谢。它根本没有引发那个异常,因为我没有在DbContext中的OnModelCreating函数中调用builder.ApplyConfiguration。。。呃……最有可能的是,
CouponMap.Configure
中的代码没有执行。@IvanStoev-实际上我是这么想的,但我的所有关系都很好(它们也在CouponMap.Configure中定义)。嗯,
Key
ValueGeneratedOnAdd
,关系-所有这些都可以在不使用fluent配置的情况下工作,因为它们符合EF核心约定。为了便于测试,请注释掉
Configure
方法的内容。或者添加类似于抛出新异常(“废话”)的内容里面。@IvanStoev-你说得对。谢谢。它根本没有引发那个异常,因为我没有在DbContext中的OnModelCreating函数中调用builder.ApplyConfiguration。。。啊。。。。