简体   繁体   中英

CRUD operations for multiple related records in different tables from single view in MVC C#

I was hoping I could get some assistance on this functionality I am trying to achieve. I have searched, but i do not seem to be able to translate the examples/tutorials I have found to make it work in my own code.

For brevity, let's say I have 2 Models with a one to many relationship between the two. Let's say it is parents and children. One parent can have zero or many children. Each child can only have 1 parent:

namespace MyApp.Models
{
  public partial class Parent 
    {
      [Key]
      public int parent_id { get; set; }
      public string parent_name { get; set; }
      public string parent_address { get; set; }
      public ICollection<Child> Child { get; set; }
    }
  public partial class Child { get; set; }
    {
      [Key]
      public int child_id { get; set; }
      public int parent_id { get; set; }
      public string child_name { get; set; }
      public string child_allergies { get; set; }
      public virtual Parent parent { get; set; } 
    }
}

Entity created the tables in the database properly, assigning primary/foreign keys where they needed to be.

I put the common fields in a viewmodel to render them in my view:

using MyApp.Models;
namespace MyApp.ViewModels
{
  public class ParentChildViewModel
    {
      public int parent_id { get; set; }
      public string parent_name { get; set; }
      public string parent_address { get; set; }
      public string child_name { get; set; }
      public string child_allergies { get; set; }
    }
}

I have my view written as below:

@model MyApp.ViewModels.ParentChildViewModel
@using (Html.BeginForm()) 
{
  <div>
    @Html.LabelFor(model => model.parent_name)
    @Html.EditorFor(model => model.parent_name)
  </div>

  <div>
    @Html.LabelFor(model => model.parent_address)
    @Html.EditorFor(model => model.parent_address)
  </div>

  <table id="child_table">
    @{ Html.RenderPartial("_children"); }
  </table>

  <div>
  <button id="add">Add Child</button>
  <button id="rem">Remove Child</button>
  </div>

  <div>
  <input type="submit" value="Create" />
  </div>
}
<script type="text/javascript">
    $("#add").click(function () {
      $.ajax({
        url: "@Url.Action("BlankChRow")",
        cache: false,
        success: function (html) {
          $("#child_table").append(html);
        }
      });
    return false;
    });
    $("#rem").click(function () {
      $("#child_table tbody tr:last")
        .remove();
      return false;
    });
</script>

I created a partial view for the child so I can repeat those:

@model MyApp.ViewModels.ParentChildViewModel
@using (Html.BeginCollectionItem("children"))
{
<tr>
  <td>
  <div>
    @Html.LabelFor(model => model.child_name)
    @Html.EditorFor(model => model.child_name)
  </div>
  </td>

  <td>
  <div>
    @Html.LabelFor(model => model.child_allergies)
    @Html.EditorFor(model => model.child_allergies)
  </div>
  </td>
</tr>
}

Then, in my controller (this is where I am stuck):

private ApplicationDbContext db = new ApplicationDbContext();

public ActionResult BlankChRow()
{
  return PartialView("_children");
}

public ActionResult Create()
{
  return View(new ParentChildViewModel());
}

[HttpPost]
public ActionResult Create(ParentChildViewModel pcvm)
{
  var parent = new Parent()
  {
    parent_id = pcvm.parent_id,
    parent_name = pcvm.parent_name,
    parent_address = pcvm.parent_address
  };
  var child = new Child()
  {
    parent_id = pcvm.parent_id,
    child_name = pcvm.child_name,
    child_allergies = pcvm.child_allergies
  };
  if (ModelState.IsValid)
  {
    db.Parent.Add(parent);
    db.Child.Add(child);
    db.SaveChanges();
    return RedirectToAction("Index");
  }
return View(pcvm);
}

I have experimented a few different ways of doing this... but I am unable to get this working the way I would like. Ideally, the View can be brought up, and while they enter the Parent's data, they could add one or many children. The children that are added would each be their own record in the Child table/entity while having the appropriate parent_id.

Any help is appreciated.

I see that you want to generate a list of children for a given parent but your viewmodel doesn't look so.

using MyApp.Models;
namespace MyApp.ViewModels
{
  public class ParentChildViewModel
    {
      public int parent_id { get; set; }
      public string parent_name { get; set; }
      public string parent_address { get; set; }
      public string child_name { get; set; }
      public string child_allergies { get; set; }
    }
}

Try a viewmodel with a list of children. Something like this :

using MyApp.Models;
namespace MyApp.ViewModels
{
  public class ParentChildViewModel
    {
      public int parent_id { get; set; }
      public string parent_name { get; set; }
      public string parent_address { get; set; }
      public IEnumerable<Child> children { get; set; }
    }
}

I'm supposing here that you just want to iterate over the list. That's why I use the IEnumerable interface instead of the IList interface.

To add a child in the list, you could call the "Create" function of your controller and pass the parent_id of the new child. In your controller you can therefore create a new child for a given parent in the database using your application context.

Once the database transaction done, you can create a new ParentChildViewModel and fulfill it with the corresponding children and return it to the view.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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