Weird behavior in linking table creation in EF Core, adding it in the DbContext but shows two versions in the migration file

huangapple go评论65阅读模式
英文:

Weird behavior in linking table creation in EF Core, adding it in the DbContext but shows two versions in the migration file

问题

在我的代码中出现了奇怪的行为。

我创建了一个 Place 实体和一个 SubCategory 实体。
因为它是多对多的关系,我创建了一个带有复合键的 PlaceSubCategory 实体。

现在,这是在 DbContext 中它的创建方式:

public DbSet<PlaceSubCategory> PlaceSubCategories { get; set; }

而这是在迁移文件中它的创建方式:

migrationBuilder.CreateTable(
	name: "PlaceSubCategories",
	columns: table => new
	{
		PlaceId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
		SubCategoryId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
		CreatedDateTime = table.Column<DateTime>(type: "datetime2", nullable: false, defaultValueSql: "getutcdate()")
	},
	constraints: table =>
	{
		table.PrimaryKey("PK_PlaceSubCategories", x => new { x.PlaceId, x.SubCategoryId });
		table.ForeignKey(
			name: "FK_PlaceSubCategories_Places_PlaceId",
			column: x => x.PlaceId,
			principalTable: "Places",
			principalColumn: "PlaceId");
		table.ForeignKey(
			name: "FK_PlaceSubCategories_SubCategories_SubCategoryId",
			column: x => x.SubCategoryId,
			principalTable: "SubCategories",
			principalColumn: "SubCategoryId");
	});

migrationBuilder.CreateTable(
	name: "PlaceSubCategory",
	columns: table => new
	{
		PlacesPlaceId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
		SubCategoriesSubCategoryId = table.Column<Guid>(type: "uniqueidentifier", nullable: false)
	},
	constraints: table =>
	{
		table.PrimaryKey("PK_PlaceSubCategory", x => new { x.PlacesPlaceId, x.SubCategoriesSubCategoryId });
		table.ForeignKey(
			name: "FK_PlaceSubCategory_Places_PlacesPlaceId",
			column: x => x.PlacesPlaceId,
			principalTable: "Places",
			principalColumn: "PlaceId",
			onDelete: ReferentialAction.Cascade);
		table.ForeignKey(
			name: "FK_PlaceSubCategory_SubCategories_SubCategoriesSubCategoryId",
			column: x => x.SubCategoriesSubCategoryId,
			principalTable: "SubCategories",
			principalColumn: "SubCategoryId",
			onDelete: ReferentialAction.Cascade);
	});

它创建了两次表,我以为这是 EF Core 的默认行为,用于创建一个后台链接表,并且在迁移文件中显示,但我不确定是否是这样。

另外,这是 PlaceSubCategory 的配置文件(不是 PlaceSubCategories):

public class PlaceSubCategoryConfiguration : IEntityTypeConfiguration<PlaceSubCategory>
{
	public void Configure(EntityTypeBuilder<PlaceSubCategory> builder)
	{
		// 为 PlaceSubCategory 表定义复合主键
		builder.HasKey(x => new { x.PlaceId, x.SubCategoryId });

		builder.HasOne<Place>(d => d.Place)
			.WithMany(d => d.SubCategoriesLink)
			.HasForeignKey(d => d.PlaceId)
			.OnDelete(DeleteBehavior.NoAction)
			.IsRequired();

		builder.HasOne<SubCategory>(d => d.SubCategory)
			.WithMany(d => d.PlacesLink)
			.HasForeignKey(d => d.SubCategoryId)
			.OnDelete(DeleteBehavior.NoAction)
			.IsRequired();

		builder.Property(p => p.CreatedDateTime)
			.HasConversion(AppDbContext.utcConverter)
			.HasDefaultValueSql("getutcdate()");
	}
}

但它没有考虑到这一点,如你可以看到在 PlaceSubCategories 的创建中删除行为不存在,但在配置文件中设置了自动删除行为,这不是我在配置文件中设置的。

当然,配置已经设置好了:

modelBuilder.ApplyConfiguration(new PlaceSubCategoryConfiguration());
英文:

I have a weird behavior happening in my code.

I've created a Place entity and a SubCategory entity.
Because it is a many to many relationship, I created a PlaceSubCategory entity with a composite key.

Now, here's what its creation looks like in the DbContext:

public DbSet&lt;PlaceSubCategory&gt; PlaceSubCategories { get; set; }

And here's what it creates in the migration file:

migrationBuilder.CreateTable(
	name: &quot;PlaceSubCategories&quot;,
	columns: table =&gt; new
	{
		PlaceId = table.Column&lt;Guid&gt;(type: &quot;uniqueidentifier&quot;, nullable: false),
		SubCategoryId = table.Column&lt;Guid&gt;(type: &quot;uniqueidentifier&quot;, nullable: false),
		CreatedDateTime = table.Column&lt;DateTime&gt;(type: &quot;datetime2&quot;, nullable: false, defaultValueSql: &quot;getutcdate()&quot;)
	},
	constraints: table =&gt;
	{
		table.PrimaryKey(&quot;PK_PlaceSubCategories&quot;, x =&gt; new { x.PlaceId, x.SubCategoryId });
		table.ForeignKey(
			name: &quot;FK_PlaceSubCategories_Places_PlaceId&quot;,
			column: x =&gt; x.PlaceId,
			principalTable: &quot;Places&quot;,
			principalColumn: &quot;PlaceId&quot;);
		table.ForeignKey(
			name: &quot;FK_PlaceSubCategories_SubCategories_SubCategoryId&quot;,
			column: x =&gt; x.SubCategoryId,
			principalTable: &quot;SubCategories&quot;,
			principalColumn: &quot;SubCategoryId&quot;);
	});

migrationBuilder.CreateTable(
	name: &quot;PlaceSubCategory&quot;,
	columns: table =&gt; new
	{
		PlacesPlaceId = table.Column&lt;Guid&gt;(type: &quot;uniqueidentifier&quot;, nullable: false),
		SubCategoriesSubCategoryId = table.Column&lt;Guid&gt;(type: &quot;uniqueidentifier&quot;, nullable: false)
	},
	constraints: table =&gt;
	{
		table.PrimaryKey(&quot;PK_PlaceSubCategory&quot;, x =&gt; new { x.PlacesPlaceId, x.SubCategoriesSubCategoryId });
		table.ForeignKey(
			name: &quot;FK_PlaceSubCategory_Places_PlacesPlaceId&quot;,
			column: x =&gt; x.PlacesPlaceId,
			principalTable: &quot;Places&quot;,
			principalColumn: &quot;PlaceId&quot;,
			onDelete: ReferentialAction.Cascade);
		table.ForeignKey(
			name: &quot;FK_PlaceSubCategory_SubCategories_SubCategoriesSubCategoryId&quot;,
			column: x =&gt; x.SubCategoriesSubCategoryId,
			principalTable: &quot;SubCategories&quot;,
			principalColumn: &quot;SubCategoryId&quot;,
			onDelete: ReferentialAction.Cascade);
	});

It creates the table twice, which I thought was the default behaviour in EF Core to create a background linking table and so it shows in the migration file, but I'm not sure if that's the case.

Also, here's the configuration file for PlaceSubCategory (and not PlaceSubCategories):

public class PlaceSubCategoryConfiguration : IEntityTypeConfiguration&lt;PlaceSubCategory&gt;
{
	public void Configure(EntityTypeBuilder&lt;PlaceSubCategory&gt; builder)
	{
		// define the composite key for PlaceSubCategory table
		builder.HasKey(x =&gt; new { x.PlaceId, x.SubCategoryId });

		builder.HasOne&lt;Place&gt;(d =&gt; d.Place)
			.WithMany(d =&gt; d.SubCategoriesLink)
			.HasForeignKey(d =&gt; d.PlaceId)
			.OnDelete(DeleteBehavior.NoAction)
			.IsRequired();

		builder.HasOne&lt;SubCategory&gt;(d =&gt; d.SubCategory)
			.WithMany(d =&gt; d.PlacesLink)
			.HasForeignKey(d =&gt; d.SubCategoryId)
			.OnDelete(DeleteBehavior.NoAction)
			.IsRequired();

		builder.Property(p =&gt; p.CreatedDateTime)
			.HasConversion(AppDbContext.utcConverter)
			.HasDefaultValueSql(&quot;getutcdate()&quot;);
	}
}

But it isn't taking it into account, as you can see by the delete behavior being non-existent in the PlaceSubCategories creation, but there's an automatically set delete behavior for
PlaceSubCategory that's not what I set in the configuration file.

And of course the configuration has been set:

modelBuilder.ApplyConfiguration(new PlaceSubCategoryConfiguration());

答案1

得分: 0

原因是通过创建这个链接实体,我正在做 EF Core 本来会做的事情,即在后台创建一个链接实体,它会显示在迁移文件中。因此,我的实体和 EF Core 的实体都被创建了,而没有警告。
我删除了我的实体,EF Core 自动创建的链接实体被添加到了迁移文件中,这似乎是可以接受的,与我自己创建的一样。

英文:

The reason was that by creating this linking entity I was doing what EF Core would do anyway which is to create a linking entity in the background that would be showing in the migration file. So my entity got created and EF Core's as well without warning.
I deleted my entity and the EF Core's automatically created linking entity got added to the migration file, which seems fine and the same thing as if I created it.

huangapple
  • 本文由 发表于 2023年6月2日 03:32:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76385145.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定