0

My code first model has a one-to-many relationship. The database is successfully generated using EF6 migrations. I've created a drop-down list but cannot update the database with the user's selection.

The LiquidFormulas table contains a foreign key GravureCylinderID (nullable) which points to the ID field in the table GravureCylinders. Here are my two model classes:

public partial class LiquidFormula
{
    public int ID { get; set; }
    ...
    public int? GravureCylinderID { get; set; }

    [ForeignKey("GravureCylinderID")]
    public virtual GravureCylinders GravureCylinder { get; set;}     
}

public class GravureCylinders
{
    public int ID { get; set; }
    ...
    public ICollection<LiquidFormula> LiquidFormulas { get; set; }
}

My LiquidFormulaViewModel references the LiquidFormula model and holds a lookup list of GravureCylinders:

public class LiquidFormulaViewModel
{
    public LiquidFormulaViewModel()
    {
        LiquidFormula = new LiquidFormula();
    }

    public LiquidFormula LiquidFormula { get; set; }
    ...
    public IEnumerable<SelectListItem> GravureCylinderList { get; set; }

In the Formulas controller I populate the lookup list:

public ActionResult Edit(int? id)
{
    LiquidFormula liquidFormula = _context.FormulasDbSet.Find(id);
    ...
    var formulaVM = new LiquidFormulaViewModel();
    formulaVM.LiquidFormula = liquidFormula;
    formulaVM.GravureCylinderList = GetListOfGravureCylinderValues();

Then in the view I display the lookup list and bind it to the foreign key:

<select asp-for="LiquidFormula.GravureCylinderID" asp-items="@Model.GravureCylinderList" class="form-control">
    <option>Select Volume in BCM</option>
</select>

I've also added this hidden field to the view:

 <input asp-for="@Model.LiquidFormula.GravureCylinder.ID" type="hidden" />

When the view form is posted I'm struggling to get the data to save properly using _context.SaveChanges(); Before SaveChanges I see the new LiquidFormula.GravureCylinderID in the ViewModel but after SaveChanges the database is NOT updated with the new ID.

EDIT: I fixed the referential integrity constraint error (below) by removing this hidden field from the view:

<input asp-for="@Model.LiquidFormula.GravureCylinder.ID" type="hidden" />

But still the database is not updating with the new LiquidFormula.GravureCylinderID.

Before _context.SaveChanges(); I get a referential constraint error on this line which is required for other work I'm doing:

_context.FormulasDbSet.Attach(modifiedFormulaVM.LiquidFormula);

Here is the error message:

A referential integrity constraint violation occurred: The property value(s) of 'GravureCylinders.ID' on one end of a relationship do not match the property value(s) of 'LiquidFormula.GravureCylinderID' on the other end.

By examining the two IDs I see that LiquidFormula.GravureCylinderID has been updated and GravureCylinders.ID has not. How can I properly update both IDs particularly GravureCylinders.ID?

DeveloperDan
  • 4,626
  • 9
  • 40
  • 65
  • View models should not contain data models, especially when editing (it should contain just a (say) `public int? SeletctedGravureCylinder { get; set; }` Why do you have a hidden input for `LiquidFormula.GravureCylinder.ID` - that will only be set to the initial value, and post back the initial value so it will not match the value from the dropdownlist. –  Nov 13 '17 at 20:42
  • Refer also [What is ViewModel in MVC?](https://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc). In the POST method you get the original data model based on its ID property and update its values from the view model and save it. –  Nov 13 '17 at 20:44
  • I've removed the hidden input and the error went away. But the database is still not updating. – DeveloperDan Nov 13 '17 at 20:49
  • Debugging I now see that before SaveChanges LiquidFormula.GravureCylinder is null but LiquidFormula.GravureCylinderID has the proper value. After SaveChanges the database is not updated. The old value stays in the LiquidFormula table (in the field GravureCylinderID) – DeveloperDan Nov 13 '17 at 20:57
  • Did you read the comment about your view model? Your view model should **NOT** contain the data model, just the properties of the data model that you need in the view. –  Nov 13 '17 at 21:00
  • That's a decision I made a long time ago and it works for me. I believe it is not related to the problem at hand. I do appreciate your help. – DeveloperDan Nov 13 '17 at 21:02
  • Unfortunately it is related to your problem. When your entities hold a reference *and* FK, you need to update the entity relationship by the reference, not the FK. The FK serves the reference, not the other way around. This means that unless your VM passes back the GravureCylinder object to set on your LiquidFormula, then you need to retrieve that newly assigned entity from the DB and associate it. Otherwise you remove the reference variable and only use the FK. Passing entities around is complex, (detach/reattach) error prone (i.e. lazy loading), and also heavyweight. (more data than needed.) – Steve Py Nov 13 '17 at 23:14

0 Answers0