C# EF Core 3.1 Fluent API未检测到实体上的更改
我正在使用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
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。。。啊。。。。