英文:
Can't Insert Data Into Many to Many Relationship With Entity Framework C# .Net7
问题
我知道这可能已经被问了数百次,如果不是数千次的话。我已经在这个问题上工作了两天,看了几个答案并尝试了几个示例。我越来越感到困惑。
我有一个论坛应用程序,有一个Forums表和一个Tags表。每个论坛可以有多个标签,每个标签可以分配给多个论坛。标签表中的每个标签都是唯一的。
public class Forum : BaseModel
{
public string? Title { get; set; }
public List<Post> Posts { get; set; } = new List<Post>();
public ICollection<ForumTag> ForumTags { get; set; } = new List<ForumTag>();
}
public class Tag : BaseModel
{
public string? Name { get; set; }
public ICollection<ForumTag> ForumTags { get; set; } = new List<ForumTag>()
}
public class ForumTag
{
public int ForumId { get; set; }
public int TagId { get; set; }
[NotMapped]
public Forum forum { get; set; } = new();
[NotMapped]
public Tag tag { get; set; } = new();
}
modelBuilder.Entity<ForumTag>()
.HasKey(t => new { t.ForumId, t.TagId });
modelBuilder.Entity<ForumTag>()
.HasOne(pt => pt.forum)
.WithMany(p => p.ForumTags)
.HasForeignKey(pt => pt.ForumId);
modelBuilder.Entity<ForumTag>()
.HasOne(pt => pt.tag)
.WithMany(t => t.ForumTags)
.HasForeignKey(pt => pt.TagId);
CreateMap<Forum, ForumViewModel>();
CreateMap<ForumViewModel, Forum>()
.ForMember(q => q.CreatedBy, options => options.Ignore());
//.ForMember(q => q.ForumTags, options => options.Ignore());
CreateMap<Post, PostViewModel>();
CreateMap<PostViewModel, Post>()
.ForMember(x => x.CreatedBy, options => options.Ignore());
CreateMap<Tag, TagViewModel>();
CreateMap<TagViewModel, Tag>()
.ForMember(x => x.Id, options => options.Ignore());
//.ForMember(x => x.ForumTags, options => options.Ignore());
//CreateMap<ForumTagViewModel, ForumTag>()
// .ForMember(q => q.forum, options => options.Ignore())
// .ForMember(q => q.tag, options => options.Ignore());
public async Task<ActionResult<ForumViewModel>> PostForum(ForumViewModel forumViewModel)
{
Forum? forum = null;
try
{
forum = _mapper.Map<Forum>(forumViewModel);
_context.Forums.Add(forum);
await _context.SaveChangesAsync();
List<ForumTag> tags = new();
foreach(TagViewModel tag in forumViewModel.SelecteTags)
{
tags.Add(new()
{
ForumId = forum.Id,
TagId = tag.Id
});
}
_context.ForumTags.AddRange(tags);
_context.SaveChanges();
}
catch (Exception ex)
{
return Problem($"Unable to post new forum.\n\n{ex}");
}
forumViewModel.Id = forum.Id;
return CreatedAtAction("GetForumViewModel", new { id = forumViewModel.Id }, forumViewModel);
}
所以目前在这个代码段之后:
forum = _mapper.Map<Forum>(forumViewModel);
_context.Forums.Add(forum);
await _context.SaveChangesAsync();
Forums表和Tag表都正确填充,以及Post表。
在此之后:
_context.ForumTags.AddRange(tags);
_context.SaveChanges();
会创建一个新的空forum记录和一个新的空tag记录。ForumTag表具有来自空forum和tag记录的ID。
我需要做的是插入一个新的forum记录,一个新的post记录和ForumTag的ID。我对Post记录没有任何问题。能否有人指点我正确的方向?
英文:
I know this has probably been asked hundreds, if not thousands of times. I have been working on this for 2 days and I have looked at several answers and tried following several examples. I have been getting more and more confused.
I have a forum app with a Forums table and a Tags table. Each forum can have many tags. Each tag can be assigned to many forums. Each tag in the tags table is unique.
public class Forum : BaseModel
{
public string? Title { get; set; }
public List<Post> Posts { get; set; } = new List<Post>();
public ICollection<ForumTag> ForumTags { get; set; } = new List<ForumTag>();
}
public class Tag : BaseModel
{
public string? Name { get; set; }
public ICollection<ForumTag> ForumTags { get; set; } = new List<ForumTag>()
}
public class ForumTag
{
public int ForumId { get; set; }
public int TagId { get; set; }
[NotMapped]
public Forum forum { get; set; } = new();
[NotMapped]
public Tag tag { get; set; } = new();
}
modelBuilder.Entity<ForumTag>()
.HasKey(t => new { t.ForumId, t.TagId });
modelBuilder.Entity<ForumTag>()
.HasOne(pt => pt.forum)
.WithMany(p => p.ForumTags)
.HasForeignKey(pt => pt.ForumId);
modelBuilder.Entity<ForumTag>()
.HasOne(pt => pt.tag)
.WithMany(t => t.ForumTags)
.HasForeignKey(pt => pt.TagId);
CreateMap<Forum, ForumViewModel>();
CreateMap<ForumViewModel, Forum>()
.ForMember(q => q.CreatedBy, options => options.Ignore());
//.ForMember(q => q.ForumTags, options => options.Ignore());
CreateMap<Post, PostViewModel>();
CreateMap<PostViewModel, Post>()
.ForMember(x => x.CreatedBy, options => options.Ignore());
CreateMap<Tag, TagViewModel>();
CreateMap<TagViewModel, Tag>()
.ForMember(x => x.Id, options => options.Ignore());
//.ForMember(x => x.ForumTags, options => options.Ignore());
//CreateMap<ForumTagViewModel, ForumTag>()
// .ForMember(q => q.forum, options => options.Ignore())
// .ForMember(q => q.tag, options => options.Ignore());
public async Task<ActionResult<ForumViewModel>> PostForum(ForumViewModel forumViewModel)
{
Forum? forum = null;
try
{
forum = _mapper.Map<Forum>(forumViewModel);
_context.Forums.Add(forum);
await _context.SaveChangesAsync();
List<ForumTag> tags = new();
foreach(TagViewModel tag in forumViewModel.SelecteTags)
{
tags.Add(new()
{
ForumId = forum.Id,
TagId = tag.Id
});
}
_context.ForumTags.AddRange(tags);
_context.SaveChanges();
}
catch (Exception ex)
{
return Problem($"Unable to post new forum.\n\n{ex}");
}
forumViewModel.Id = forum.Id;
return CreatedAtAction("GetForumViewModel", new { id = forumViewModel.Id }, forumViewModel);
}
So currently after
forum = _mapper.Map<Forum>(forumViewModel);
_context.Forums.Add(forum);
await _context.SaveChangesAsync();
The forums table and Tag table are correctly populated, as well as the Post table.
After
_context.ForumTags.AddRange(tags);
_context.SaveChanges();
A new null forum record is created and a new null tag record is created. The ForumTag table has the id's from the null forum and tag record.
What I need to do is insert a new forum record, a new post record, and the ForumTag Id's. I'm not having any issues with the Post records.
Can someone please point me in the right direction?
答案1
得分: 0
以下是翻译好的部分:
好吧,像往常一样,我在发布帖子后才弄清楚了。我找到了这篇博客[在EF Core 5及以上版本中更新多对多关系][1]
public class Forum : BaseModel
{
public string? Title { get; set; }
public List<Post> Posts { get; set; } = new List<Post>();
public List<Tag>? Tags { get; set; }
}
public class Tag : BaseModel
{
public string? Name { get; set; }
public ICollection<Forum> Forums { get; set; }
}
public class ForumTag
{
public int ForumId { get; set; }
public int TagId { get; set; }
public Forum forum { get; private set; }
public Tag tag { get; private set; }
}
modelBuilder.Entity<Forum>().HasMany(x => x.Tags)
.WithMany(x => x.Forums)
.UsingEntity<ForumTag>(
x => x.HasOne(x => x.tag)
.WithMany().HasForeignKey(x => x.TagId),
x => x.HasOne(x => x.forum)
.WithMany().HasForeignKey(x => x.ForumId));
public async Task<ActionResult<ForumViewModel>> PostForum(ForumViewModel forumViewModel)
{
Forum? forum = null;
try
{
var viewModelTags = forumViewModel.SelecteTags;
List<Tag> tags = new List<Tag>();
foreach (var item in viewModelTags)
{
Tag tag = await _context.Tags.FirstOrDefaultAsync(x => x.Name == item.Name);
tags.Add(tag);
}
forum = _mapper.Map<Forum>(forumViewModel);
forum.Tags = new();
forum.Tags.AddRange(tags);
_context.Add(forum);
_context.SaveChanges();
}
catch (Exception ex)
{
return Problem($"无法发布新的论坛。\n\n{ex}");
}
forumViewModel.Id = forum.Id;
return CreatedAtAction("GetForumViewModel", new { id = forumViewModel.Id }, forumViewModel);
}
<details>
<summary>英文:</summary>
Well, as happens from time to time, I figured it out after I created a post here. I found this blog [Updating many-to-many relationships in EF Core 5 and above][1]
public class Forum : BaseModel
{
public string? Title { get; set; }
public List<Post> Posts { get; set; } = new List<Post>();
public List<Tag>? Tags { get; set; }
}
public class Tag : BaseModel
{
public string? Name { get; set; }
public ICollection<Forum> Forums { get; set; }
}
public class ForumTag
{
public int ForumId { get; set; }
public int TagId { get; set; }
public Forum forum { get; private set; }
public Tag tag { get; private set; }
}
modelBuilder.Entity<Forum>().HasMany(x => x.Tags)
.WithMany(x => x.Forums)
.UsingEntity<ForumTag>(
x => x.HasOne(x => x.tag)
.WithMany().HasForeignKey(x => x.TagId),
x => x.HasOne(x => x.forum)
.WithMany().HasForeignKey(x => x.ForumId));
public async Task<ActionResult<ForumViewModel>> PostForum(ForumViewModel forumViewModel)
{
Forum? forum = null;
try
{
var viewModelTags = forumViewModel.SelecteTags;
List<Tag> tags = new List<Tag>();
foreach (var item in viewModelTags)
{
Tag tag = await _context.Tags.FirstOrDefaultAsync(x => x.Name == item.Name);
tags.Add(tag);
}
forum = _mapper.Map<Forum>(forumViewModel);
forum.Tags = new();
forum.Tags.AddRange(tags);
_context.Add(forum);
_context.SaveChanges();
}
catch (Exception ex)
{
return Problem($"Unable to post new forum.\n\n{ex}");
}
forumViewModel.Id = forum.Id;
return CreatedAtAction("GetForumViewModel", new { id = forumViewModel.Id }, forumViewModel);
}
[1]: https://www.thereformedprogrammer.net/updating-many-to-many-relationships-in-ef-core-5-and-above/
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论