Reputation: 528
I am using ASP.NET and I have two models, Contact and Customer and there is a one to one relationship between the two. So, every contact will be added in the contacts entity and when a contact is a customer, the extra information will be added in the customer entity.
I created a ViewModel containing both. When the view model is then passed in the post request, i add first the contact, which adds correctly and then I want to add the customer with relationship to the previous contact, but I don't know how to do it.
[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();
}
UPDATE
These are the classes for my models:
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; }
}
And here is the view
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>
}
Upvotes: 0
Views: 656
Reputation: 785
You have to understand what happens behind the scenes to understand why this doesn't work.
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();
}
If you want this entire operation to be atomic you'll have to wrap it in a transaction, like so:
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();
}
Upvotes: 2
Reputation: 772
I'm not sure but maybe you should change the order and you probably don't have to add contact explicit:
customerViewModel.customer.Contact = customerViewModel.contact;
db.Contact.Add(customerViewModel.customer);
db.SaveChanges();
Upvotes: 0