Based on the tutorial from MS: https://learn.microsoft.com/en-us/ef/core/modeling/relationships?tabs=fluent-api%2Cfluent-api-simple-key%2Csimple-key
This is how we define Post and Tag which have many-many relationship to each other:
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public ICollection<Tag> Tags { get; set; }
}
public class Tag
{
public string TagId { get; set; }
public ICollection<Post> Posts { get; set; }
}
When I run the database-update, it has been able to generate three tables: Post
, Tag
and PostTag
which have the primary key [PostId, TagId]
. Overall, the database schema is exactly what I thought.
However, what not mentioned is how to insert a Post
with relationship with Tags
or vice versa.
db.Posts.Add(new Post { Title="Title1", Content="Content1"});
db.Posts.Add(new Post { Title="Title2", Content="Content2"});
db.Tags.Add(new Tag { TagId="Tag1"});
db.Tags.Add(new Tag { TagId="Tag2"});
db.SaveChanges();
Now the database has 2 records in each table. My question is how can we add a new post that has tag1 and tag2? My code below doesn't work. Can someone point out what was wrong? Or do I need to do the old way by adding a third entity PostTag
?
This is my code:
ICollection<Tag> tags = new List<Tag> {db.Tags.FirstOrDefault(i => i.TagId="Tag1"), db.Tags.FirstOrDefault(i => i.TagId="Tag2")};
db.Posts.Add(new Post { Title="Title3", Content="Content3", Tags=tags});
db.SaveChanges();
What I got is the exception saying it cannot insert post3 to the database.
Updated: Thanks for everyone's help. Found out that I made a mistake in my real code. This is my actual code:
vICollection<Tag> tags = new List<Tag> {db.Tags.FirstOrDefault(i => i.TagId="Tag1"), db.Tags.FirstOrDefault(i => i.TagId="Tag2")};
var post3 = new Post { Title="Title3", Content="Content3"};
db.Posts.Add(post3);
post3.Tags = tags; // wrong position, should be called before db.Posts.Add(post3)
db.SaveChanges();
The mistake is post3.Tags = tags;
is called after db.Posts.Add(post3);
. It should be like this:
vICollection<Tag> tags = new List<Tag> {db.Tags.FirstOrDefault(i => i.TagId="Tag1"), db.Tags.FirstOrDefault(i => i.TagId="Tag2")};
var post3 = new Post { Title="Title3", Content="Content3"};
post3.Tags = tags; // correct position
db.Posts.Add(post3);
db.SaveChanges();
I have also removed PostId from my code.
When you add the Post
with specifying the PostId
,it will get the following error:
Cannot insert explicit value for identity column in table 'Posts' when IDENTITY_INSERT is set to OFF.
Just remove the PostId
and the code will work fine:
ICollection<Tag> tags = new List<Tag> {
db.Tags.FirstOrDefault(i => i.TagId="Tag1"),
db.Tags.FirstOrDefault(i => i.TagId="Tag2")};
db.Posts.Add(new Post { Title="Title3", Content="Content3", Tags=tags});
db.SaveChanges();