MVC ASP.NET 创建在单个视图中关联的两个模型

MVC ASP.NET Creating two models that are associated in a single view

我正在使用 ASP.NET,我有两个模型,Contact 和 Customer,两者之间存在一对一的关系。因此,每个联系人都将添加到联系人实体中,当联系人是客户时,额外的信息将添加到客户实体中。

我创建了一个包含两者的 ViewModel。然后在 post 请求中传递视图模型时,我首先添加联系人,它添加正确,然后我想添加与前一个联系人有关系的客户,但我不知道该怎么做.

[HttpPost]
public ActionResult CustomerCreate(CustomerViewModel customerViewModel)
{
    if (ModelState.IsValid)
    {
        try
        {
            using (var db = new ModelContactContainer())
            {
                db.Contact.Add(customerViewModel.contact);
                customerViewModel.customer.Contact = customerViewModel.contact;
                db.Customer.Add(customerViewModel.customer);
                db.SaveChanges();
            }
            return RedirectToAction("Index");
        }
        catch
        {
            return CustomerCreate();
        }
    }
    return CustomerCreate();
}

更新

这些是我的模型的 类:

Contact.cs

using System;
using System.Collections.Generic;
public partial class Contact
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual Customer Customer { get; set; }
}

Customer.cs

using System;
using System.Collections.Generic;

using System.ComponentModel.DataAnnotations;

public partial class Customer
{
    public int Id { get; set; }
    public string Something { get; set; }

    [Required]
    public virtual Contact Contact { get; set; }
}

CustomerViewModel.cs

public class CustomerViewModel
    {
        public Contact contact { get; set; }
        public Customer customer { get; set; }
    }

这是风景

CustomerCreate.cshtml

@model W3SchoolsApplication.Models.CustomerViewModel
@{
    ViewBag.Title = "Create Customer";
}

<h2>@ViewBag.Title</h2>

@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.contact.Name, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.contact.Name, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.contact.Name, "", new { @class = "text-danger" })
            </div>
        </div>
        <div class="form-group">
            @Html.LabelFor(model => model.customer.Something, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.customer.Something, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.customer.Something, "", new { @class = "text-danger" })
            </div>

        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

我不确定,但也许您应该更改顺序并且您可能不必显式添加联系人:

        customerViewModel.customer.Contact = customerViewModel.contact;
        db.Contact.Add(customerViewModel.customer);
        db.SaveChanges();

您必须了解幕后发生的事情才能理解为什么这不起作用。

using (var db = new ModelContactContainer())
{
    db.Contact.Add(customerViewModel.contact);
    db.SaveChanges(); // so the above has an ID and the foreign key relationship works

    // this doesn't add anything to the database, it just populates the foreign key relationship
    customerViewModel.customer.Contact = customerViewModel.contact; 
    db.Customer.Add(customerViewModel.customer);
    db.SaveChanges();
}

如果您希望整个操作是原子的,您必须将其包装在事务中,如下所示:

using (var db = new ModelContactContainer())
using (var transaction = db.Database.BeginTransaction())
{
    db.Contact.Add(customerViewModel.contact);
    db.SaveChanges();

    customerViewModel.customer.Contact = customerViewModel.contact; 
    db.Customer.Add(customerViewModel.customer);
    db.SaveChanges();

    transaction.Commit();
}