保存并阅读复选框值 - 多对多关系c#

时间:2018-03-07 14:31:25

标签: c# asp.net-mvc razor many-to-many

在多对多关系中从表中实现读取和保存值的最佳方法是什么? 我想为选定的技术设置复选框或类似的东西。

我有表问题

public int Id { get; set; }
public string Name{ get; set; }
public Country Country { get; set; }
public int? CountryId { get; set; }

public ICollection<Technology> Technologies { get; set; }

技术

public int Id { get; set; }
public string Name{ get; set; }
public ICollection<Question> Questions{ get; set; }

我使用属性创建了ViewModel QuestionViewModel - 不确定是否有必要

public int Id { get; set; }
public string Description { get; set; }
public IEnumerable<Technology> Technologies { get; set; } // not sure about this

保存无表技术。

也许我需要使用 ICollection Technologies ICollection Questions 类来代替我当前的ViewModel?

Razor页面是没有Technology类的简单表单,也不确定如何实现。 实体框架从代码优先方法创建了表 TechnologyQuestions

保存操作如下所示

public ActionResult Save(Question question)
{
            if (!ModelState.IsValid)
            {
                var viewModel = new QuestionViewModel
                {
                    Countries = _context.Countries.ToList()
                };
                return View("NewForm", viewModel);
            }

            if (question.Id == 0)
                _context.Questions.Add(question);
            else
            {
                var questionInDb = _context.Questions.Single(q => q.Id == question.Id);

                questionInDb.Name= question.Name;
                questionInDb.CountryId = question.CountryId;

            }

            _context.SaveChanges();

            return RedirectToAction("Index", "Home");
        }

我正在使用C#MVC 5.感谢任何帮助或指导。

2 个答案:

答案 0 :(得分:0)

当你添加表格技术时,你没有说出什么是无效的,所以我假设你的问题是EF在你将它们链接到问题时试图插入新技术。

您应该首先尝试将Technology对象附加到上下文:

if (question.Id == 0) 
{
    foreach(var tech in question.Technologies)
        _context.Technologies.Attach(tech)
    _context.Questions.Add(question);
}
else
{
    var questionInDb = _context.Questions.Single(q => q.Id == question.Id);

    questionInDb.Name= question.Name;
    questionInDb.CountryId = question.CountryId;

    foreach(var tech in question.Technologies.Where(t => !questionInDb.Technologies.Any(x => x.Id == t.Id)))
        _context.Technologies.Attach(tech);

    //Remove Technologies that have been unchecked in the page
    //...
}

答案 1 :(得分:0)

我已经解决了这个问题。

QuestionViewModel 具有ICollection of Technology类。

保存操作中,我有

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Save(Question question, string[] techIds)
{
   UpdatePostCategories(question, techIds);
   ....
   _context.Questions.Add(question);
   _context.SaveChanges();
}

UpdatePostCategories 方法如下所示

private void UpdatePostCategories(Question question, string[] techIds)
{
    var selectedCategoriesHS = new HashSet<string>(techIds);
    var postCategories = new HashSet<int>
           (question.Technologies.Select(t=> t.Id));

        foreach (var item in _context.Technologies)
        {
            if (selectedCategoriesHS.Contains(item.Id.ToString()))
            {
                if (!postCategories.Contains(item.Id))
                {
                    question.Technologies.Add(item);
                }
            }
            else
            {
                if (postCategories.Contains(item.Id))
                {
                    question.Technologies.Remove(item);
                }
            }
        }
    }

在我的View复选框中,您可以选择所有技术,如下所示

<div class="form-group">
    @foreach (var item in Model.Technologies)
    {
       <div>
         <label>@Html.DisplayFor(model => item.Name)</label>
         <input type="checkbox" value="@item.Id" name="techIds" />
       </div>
    }
</div>