builder.Entity<RecipeTag>().HasOne(rt => rt.Recipe).WithMany(r => r.RecipeTags).HasForeignKey(rt => rt.RecipeId);
然后添加
晚上好:-)
关于EFCore多对多INSERT案例,我无法回答。
我有一个Recipe
,其中有很多Tag
。一个Tag
(例如“晚餐”)可以在多个Recipe
中。两者都有其SQL表。
为了进行多对多工作,我还具有一个联接的SQL表及其关联的对象RecipeTag
。
注意#1:班级代码在这篇文章的结尾
注#2:每个GET / SELECT操作都像一个超级按钮,实现了多对多并且有效
举个简单的例子,从新的空表开始,我发布新的Recipe
:
POST /recipes
{
"title": "A first title",
"tags": [
{
"name": "dinner"
}
]
}
很好。我在Recipe
表,Tag
表和RecipeTag
表中都链接了两个id
。
现在,我用same
Recipe
:]重新注册一个新的Tag
。是否有解决此问题的好方法?意思是,要让EF Core也注册第二个POST /recipes { "title": "A second title", "tags": [ { "name": "dinner" } ] }
在这里,我从EF Core获得了唯一键约束违规。它将尝试使用名称
Tag
注册一个新的dinner
。因为我已经在Tag
。tagnam
字段中添加了唯一的约束,所以异常实际上很正常。Question:
Recipe
和加入的RecipeTag
实体,就认识到Tag
本身存在,不仅这次不是通过PK,而是通过唯一约束。似乎(并且这是逻辑)如果EF Core看到id
(PK)已存在于db中,则不会尝试添加实体。但在我的情况下:我也希望EF Core也检查唯一约束,如果发生冲突,则将db中有冲突的实体的id
和我的Tag
对象中的lazy-put-it都使用,以便它可以( )用正确的RecipeTag
正确插入id
加入实体!
对不起,这有点混乱...
我目前唯一的“不太糟糕”的解决方案:
RecipeDto
string[]
RecipeDto
转换为Recipe
时,字段ICollection<RecipeTag>
将包含适当的Tag
,其中id
设置为现有对象,某些no-id Tag
对象,对于我们的对象确实需要添加Tag
填充了一个ID,并且不会尝试将其插入db-它只会插入不带id的那些[]我使用的班级:
/// <summary>
/// Recipe that can contain many tags
/// </summary>
[Table("rcp")]
public class Recipe
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("id")]
public Guid Id { get; set; }
[Column("rcptit")]
public string Title { get; set; }
public ICollection<RecipeTag> RecipeTags { get; set; }
}
/// <summary>
/// Tag contained into many recipes
/// </summary>
[Table("tag")]
public class Tag
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("id")]
public Guid Id { get; set; }
[Column("tagnam")] // this has a UNIQUE constraint in db to avoid having 2 times the same tag
public string Name { get; set; }
}
/// <summary>
/// Join table between Recipes and Tags
/// </summary>
[Table("rcptag")]
public class RecipeTag
{
[Column("rcpid")]
public Guid RecipeId { get; set; }
[Column("tagid")]
public Guid TagId { get; set; }
public Recipe Recipe { get; set; }
public Tag Tag { get; set; }
}
public class MyDbContext : DbContext
{
public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
{ }
public DbSet<Recipe> Recipes { get; set; }
public DbSet<Tag> Tags { get; set; }
public DbSet<RecipeTag> RecipeTags { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.HasPostgresExtension("uuid-ossp");
builder.Entity<Tag>().HasIndex(e => e.Name).IsUnique();
// composite primary key for RecipeTag
builder.Entity<RecipeTag>().HasKey(rt => new { rt.RecipeId, rt.TagId });
builder.Entity<RecipeTag>().HasOne(rt => rt.Recipe).WithMany(r => r.RecipeTags).HasForeignKey(rt => rt.RecipeId);
}
}
[晚上好:-)关于EFCore的多对多INSERT案例,我有一个我无法回答的问题。我的食谱有很多标签。标签(例如“晚餐”)可以存在于许多配方中。两者...
builder.Entity<RecipeTag>().HasOne(rt => rt.Recipe).WithMany(r => r.RecipeTags).HasForeignKey(rt => rt.RecipeId);
然后添加
builder.Entity<RecipeTag>().HasOne(rt => rt.Tag).WithMany(r => r.RecipeTags).HasForeignKey(rt => rt.TagId).IsRequired(); builder.Entity<RecipeTag>().HasOne(rt => rt.Recipe).WithMany(r => r.RecipeTags).HasForeignKey(rt => rt.RecipeId).IsRequired();
这定义了组合键两侧的关系。