简体   繁体   English

多对多 Entity Framework Core 如何插入

[英]Many to many Entity Framework Core how to insert

Based on the tutorial from MS: https://docs.microsoft.com/en-us/ef/core/modeling/relationships?tabs=fluent-api%2Cfluent-api-simple-key%2Csimple-key基于 MS 的教程: https://docs.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:这就是我们如何定义彼此具有多对多关系的 Post 和 Tag:

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] .当我运行数据库更新时,它能够生成三个表: PostTagPostTag ,它们具有主键[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.但是,没有提到的是如何插入与Tags有关系的Post ,反之亦然。

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.现在数据库在每个表中有 2 条记录。 My question is how can we add a new post that has tag1 and tag2?我的问题是我们如何添加具有 tag1 和 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 ?还是我需要通过添加第三个实体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.我得到的是异常说它不能将 post3 插入数据库。

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;错误是post3.Tags = tags; is called after db.Posts.Add(post3);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.我还从我的代码中删除了 PostId。

When you add the Post with specifying the PostId ,it will get the following error:当您添加Post并指定PostId时,将收到以下错误:

Cannot insert explicit value for identity column in table 'Posts' when IDENTITY_INSERT is set to OFF.当 IDENTITY_INSERT 设置为 OFF 时,无法在表“帖子”中插入标识列的显式值。

Just remove the PostId and the code will work fine:只需删除PostId ,代码就可以正常工作:

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();

As @Rena already mentioned, your code is failing to work because you are setting primary-key value ( PostId=3 ) while creating the Post entity.正如@Rena 已经提到的,您的代码无法工作,因为您在创建Post实体时设置了主键值( PostId=3 )。 I'll just add an improvement point.我只是添加一个改进点。

In the code below, you are doing multiple trip to the database to fetch one Tag at a time -在下面的代码中,您正在多次访问数据库以一次获取一个Tag -

ICollection<Tag> tags = new List<Tag> {db.Tags.FirstOrDefault(i => i.TagId="Tag1"), db.Tags.FirstOrDefault(i => i.TagId="Tag2")};

You could just fetch the list of tags in one go, like -您可以只获取一个 go 中的标签列表,例如 -

var tags = db.Tags.ToList();

and your final code might look like -你的最终代码可能看起来像 -

var tags = db.Tags.ToList();
var post = new Post
{
    Title = "Title3",
    Content = "Content3",
    Tags = tags.Where.(i => i.TagId == "Tag1" || i.TagId == "Tag2")).ToList()
}
db.Posts.Add(post);
db.SaveChanges()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM