No way to save entity when navigation properties are null, but Ids are filled

301 Views Asked by At

I recently migrated my project to MVC4 Web API. Prior to that I used standard MVC controllers. Upon postback of an entity, I used UpdateModel to update the model and then persist it to the database with [dbContext].SaveChanges();

All worked fine, but in Web API there is no UpdateModel. So I looked for an alternative: AutoMapper.

I use EF 5 code first and I use the entity classes as models for MVC.

My model class (simplified) looks as follows:

public class Model
{
    [ForeignKey("Parent")]
    public Guid ParentId { get; set; }
    [IgnoreDataMember]
    public TParentEntity Parent { get; set; }

    public string Name { get; get; }
}

When the model is send in JSON, the Parent property is ignored during serialization.

Thus when the PUT (update) method is called on my api controller with the entity, the Parent property is empty.

Here's the code of the PUT method:

public void Put(Model model)
{
    var contextModel = Repository.GetOne(model.Id);
    Mapper.CreateMap<Model , Model>();
    Mapper.Map(model, contextModel);
    Repository.Update();
}

The Parent property is null in model, but not in contextModel. AutoMapper just overwrites the Parent property in contextModel with null.

Then, when I save I get an InvalidOperationException, despite the fact that ParentId is present:

The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.

Any solution or advice on how to do this differently is appreciated.

1

There are 1 best solutions below

0
On

I'd highly recommend not posting back your entities and using a dto instead, with only the properties you want to be able to update.

However, you could get around this issue (for now) by adding an ignore to your mapping rules.

Mapper.CreateMap<Model , Model>().For(m => m.Parent, opt => opt.Ignore());