实体框架-具有多对多映射的插入模型 [英] Entity Framework - Inserting model with many to many mapping
问题描述
当我具有这样的模型设置时,如何插入属于模型 Post
的模型 Tag
:
How can I insert a model Tag
that belongs to a model Post
when I have the models setup like this:
发布
public class Post
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
public Post()
{
Tags = new List<Tag>();
}
}
标记
public class Tag
{
public int Id { get; set; }
public string Name { get; set; }
}
此问题建议创建一个Post对象,然后将Tags添加到Tags集合,我无法正常运行:
插入/更新多对多实体框架。我该怎么做?
This question suggests to create a Post object then add Tags to the Tags collection, I couldn't get it working: Insert/Update Many to Many Entity Framework . How do I do it?
我想在数据库中已经将Tag添加到Post,我该如何使用EF。我是EF的新手。
I want to add Tag to Post already in the database, how can I do that with EF. I'm new to EF.
这是我尝试过的方法,如果将其发送到API,则不会插入任何记录,并且可以看到新的 tag Id = 0
在数据库中不存在,但是我认为这会导致外键约束错误,不确定是否需要执行某些操作为标签自动生成ID:
This is what I've tried, if I send this to the API it doesn't insert any records and I can see that the new tag Id = 0
which doesn't exist in the database, but I'd think that'd cause a foreign key constraint error, not sure If I need to do something to auto generate Id for the tag:
{
Name: "test"
}
API
[ResponseType(typeof(Tag))]
public IHttpActionResult PostTag(Tag tag)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var post = new Post();
var tags = new List<Tag>();
tags.Add(tag);
post.Tags.Add(tag);
post.Id = 10;
db.Entry(post).State = EntityState.Modified;
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = tag.Id }, tag);
}
推荐答案
如果您说有多对多
关系,其中 PostTag
是 Tag $ c $之间的连接表c>和
Post
,那么您的模型没有显示任何多对多
关系,所以从我的情况来看看到在 Post
和 Tag之间有
一对多
code>,因为您的模型定义。
If you said there is Many-To-Many
relation which the PostTag
is connection table between Tag
and Post
then your models don't show any many-to-many
relation, so from what I have seen there is
one-to-many
between Post
and Tag
because of your model definition.
如果要建立多对多
关系在它们之间,您必须执行以下操作:
if you want to make many-to-many
relation between them you have to something like below:
public class Tag
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Post> Posts { get; set; }
public Tag()
{
Posts = new HashSet<Post>();
}
}
public class Post
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
public Post()
{
Tags = new HashSet<Tag>();
}
}
和 OnModelCreating
通过fluent api建立联系,如下所示:
and in OnModelCreating
make relation by fluent api as below :
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Tag>()
.HasMany(s => s.Posts)
.WithMany(c => c.Tags)
.Map(cs =>
{
cs.MapLeftKey("TagId");//TagId
cs.MapRightKey("PostId");//PostId
cs.ToTable("PostTag");
});
}
反之亦然
modelBuilder.Entity<Post>()
.HasMany(s => s.Tags)
.WithMany(c => c.Posts)
.Map(cs =>
{
cs.MapLeftKey("PostId");//PostId
cs.MapRightKey("TagId");//TagId
cs.ToTable("PostTag");
});
您可以看到并知道应该有一个名为 PostTag的表数据库中的code>有两列作为键,这些脚本具有以下脚本:
as you can see and know there should be a table named PostTag
in database which have two columns as keys which have a script like :
CREATE TABLE [dbo].[PostTag](
[TagId] [int] NOT NULL,
[PostId] [int] NOT NULL,
CONSTRAINT [PK_PostTag] PRIMARY KEY CLUSTERED
(
[TagId] ASC,
[PostId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE [dbo].[PostTag] WITH CHECK ADD CONSTRAINT [FK_PostTag_Post] FOREIGN KEY([PostId])
REFERENCES [dbo].[Post] ([Id])
GO
ALTER TABLE [dbo].[PostTag] CHECK CONSTRAINT [FK_PostTag_Post]
GO
ALTER TABLE [dbo].[PostTag] WITH CHECK ADD CONSTRAINT [FK_PostTag_Tag] FOREIGN KEY([TagId])
REFERENCES [dbo].[Tag] ([TagId])
GO
ALTER TABLE [dbo].[PostTag] CHECK CONSTRAINT [FK_PostTag_Tag]
GO
看看此处以获取更多信息。
更新:
如果要建立零对多
关系, code> Post 和 Tag
,则模型应如下所示:
if you want establish zero-to-many
relation between Post
and Tag
then the models should be like below:
public class Tag
{
public int Id { get; set; }
public string Name { get; set; }
public int? PostId { get; set; }
}
public class Post
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
public Post()
{
Tags = new HashSet<Tag>();
}
}
以及与流利api的一对多关系:
and one to many relation with fluent api :
modelBuilder.Entity<Post>()
.HasMany(o1 => o1.Tags);
作为您的注释,您不需要 Tag
具有导航属性,因此如果存在关联,则应在 Tag
中将其定义为 Nullable
这是伪键在它们之间,您至少应该通过Navigation属性或 Nullable
属性建立关系。
as your comment you don't want Tag
have navigate property so you should define a property as Nullable
in Tag
which is feign key, if there is a relation between them you should establish relation at least by navigate property or Nullable
property.
正确答案来自此处(无更改):
如果您想为存在的帖子分配标签,则应该先找到该帖子,然后再向其中添加标签标签确实存在于数据库中,将在Tag和发现的Post之间建立关系,如果该Tag不存在,则将标签插入数据库,
The correct answer came from here (with no change): You want to assign a tag to exist post you should find that Post firstly then add a tag to it, if that tag does exist in DB a relation will be made between Tag and found Post if that Tag does not exist then Tag will be inserted to DB,
看看这个:
var post = context.Posts.SingleOrDefault(x => x.Id == 4);//That Id would be you specific Post Id
var existTag = context.Tags.SingleOrDefault(x => x.Id == 1); //Exist Tag in DB
post.Tags.Add(existTag);
context.SaveChanges();
//Inserting new tag to DB and assign it to Post also
Tag newTag = new Tag // Does not exist in DataBase
{
Name = "tag2"
};
post.Tags.Add(newTag);// By this tag2 will be insert into Tag table first and then added to post (insert new record to PostTag)
context.SaveChanges();
这篇关于实体框架-具有多对多映射的插入模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!