简体   繁体   English

ASP MVC 实体框架核心。 在表单帖子上更新多对多关系

[英]ASP MVC Entity Framework core. Update many to many relationship on form post

I'd like to know a good practice to update a many to many relationship when submit form.我想知道在提交表单时更新多对多关系的好做法。

I got these two entities and I use the default many to many relationship from EF core 5:我得到了这两个实体,并使用了 EF 核心 5 中的默认多对多关系:

public class BlogEntry
   {
      public int Id { get; set; }
      [Required]
      [MaxLength(200)]
      public string Title { get; set; }
      [Required]
      public string EntryText { get; set; }
      [NotMapped] 
      public IEnumerable<string> CategoriesToPublish { get; set; } 
      public ICollection<Category> Categories { get; set; } 

   }
   public class Category
   {
      public int Id { get; set; }
      public string Name { get; set; }
      public ICollection<BlogEntry> BlogEntries { get; set; }
   }

context:语境:

      public DbSet<BlogEntry> BlogEntries { get; set; }
      public DbSet<Category> Categories { get; set; }

And I have a form witha multiselect field to represent this relationship.我有一个带有多选字段的表单来表示这种关系。 See Image form见图像形式

I'm not using the relation property on the form(maube I should, but I don't know), I have another property to convert the relationship into a list of strings called CategoriesToPublish so I can load the multiselect and retrieve the selection on post.我没有在表单上使用关系属性(我应该使用,但我不知道),我有另一个属性可以将关系转换为名为CategoriesToPublish的字符串列表,以便我可以加载多选并检索选择邮政。

On the post action method, I want to iterate the this CategoriesToPublish and update all the relationships.在 post action 方法上,我想迭代 this CategoriesToPublish并更新所有关系。

      [HttpPost]
      [ValidateAntiForgeryToken]
      public async Task<IActionResult> Publish(BlogEntry blogEntry)
      {
         if (ModelState.IsValid)
         {
            blogEntry.Categories = await _context.Categories.Where(x => x.BlogEntries.Any(x => x.Id == blogEntry.Id)).ToListAsync();
            await UpdateCategories(blogEntry);
            _context.Update(blogEntry);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(List));
         }
         return View(blogEntry);
      }

But the problem that I'm facing is that the Categories relationship is not loaded on postback.但我面临的问题是Categories关系没有在回发时加载。 And if I try to load it manually and save context, I get an error saying SqlException: Violation of PRIMARY KEY constraint 'PK_BlogEntryCategory'. Cannot insert duplicate key in object 'dbo.BlogEntryCategory'如果我尝试手动加载它并保存上下文,我会收到一条错误消息,指出SqlException: Violation of PRIMARY KEY constraint 'PK_BlogEntryCategory'. Cannot insert duplicate key in object 'dbo.BlogEntryCategory' SqlException: Violation of PRIMARY KEY constraint 'PK_BlogEntryCategory'. Cannot insert duplicate key in object 'dbo.BlogEntryCategory'

I am not sure how to approach this problem.我不知道如何解决这个问题。 Any advice?有什么建议吗?

After lot of searching I found out a solution.经过大量搜索,我找到了解决方案。

      [HttpPost]
      [ValidateAntiForgeryToken]
      public async Task<IActionResult> Publish(BlogEntry blogEntry)
      {
         if (ModelState.IsValid)
         {
            blogEntry = _context.Update(blogEntry).Entity;
            blogEntry.Categories = await _context.Entry(blogEntry).Collection(u => u.Categories).Query().ToListAsync();
            await UpdateCategories(blogEntry);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(List));
         }
         return View(blogEntry);
      }

I retrieve the blogEntry after Update :我在Update后检索 blogEntry :

blogEntry = _context.Update(blogEntry).Entity;

At this point the Categories are still empty, but now we can load them from DB again:此时Categories仍然是空的,但现在我们可以再次从数据库加载它们:

blogEntry.Categories = await _context.Entry(blogEntry).Collection(u => u.Categories).Query().ToListAsync();

and boila, now we are good to iterate all the Categories change them if needed, it doesn't complain about duplicate keys.和 boola,现在我们可以迭代所有类别,如果需要更改它们,它不会抱怨重复键。

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

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