0

I'm trying to work my way through a Dot Net Core MVC project, but I am facing a problem I couldn't solve.
And honestly, I didn't know what to search for.
The project is a simple vehicle registry, Each vehicle has a Make, a Model, a some Features. Here are the domain models:

    public class Make
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public ICollection<Model> Models { get; set; }

        public Make()
        {
            Models=new Collection<Model>();
        }
    }

    public class Model
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public Make Make { get; set; }

        public int MakeId { get; set; }

        public Model()
        {
            Make=new Make();
        }
    }

    public class Feature
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    [Table(name:"VehicleFeatures")]
    public class VehicleFeature
    {
        public int VehicleId { get; set; }
        public int FeatureId { get; set; }
        public Feature Feature { get; set; }
        public Vehicle Vehicle { get; set; }

        public VehicleFeature()
        {
            Feature=new Feature();
            Vehicle=new Vehicle();
        }
    }

    public class Vehicle
    {
        public int Id { get; set; }
        public Model Model { get; set; }
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int ModelId { get; set; }
        public ICollection<VehicleFeature> VehicleFeatures { get; set; }
        public string ContactName { get; set; }
        public string ContactPhone { get; set; }
        public string ContactEmail { get; set; }
        public DateTime LastUpdate { get; set; }
        public bool IsRegistered { get; set; }

        public Vehicle()
        {
            Model=new Model();
            VehicleFeatures=new Collection<VehicleFeature>();
        }
    }

The problem is that when I send the following request to the corresponding controller, EF is replacing the provided value with a new incremental value.
The request I send:

{
    "ModelId":10,
    "VehicleFeatures":[
        {"featureId":45},
        {"featureId":46}
        ],
    "ContactName":"Alice",
    "ContactPhone":"1234",
    "ContactEmail":"Alice@local",
    "LastUpdate":"1980-01-01",
    "IsRegistered":true
}

And this is what happens:
The controller receives correct values, 1 Correct values are added to the context, 2 And then suddenly all hell breaks loose. 3

This is the controller code:

  [HttpPost]
  public async Task<IActionResult> CreateVehicle([FromBody] Vehicle v)
        {
            context.Vehicles.Add(v);
            await context.SaveChangesAsync();
            return Ok(v.ModelId);
        }

What am I missing here?

Sam
  • 489
  • 5
  • 22
  • Why are you assigning `new Model()` to `Vehlcle.Model`? – CodeCaster Apr 17 '18 at 07:27
  • @CodeCaster To prevent null reference exception from happening by accessing/assigning a Vehicle's model without it being initialized first. Am I doing it wrong? Is this the cause you think? – Sam Apr 17 '18 at 07:32
  • 2
    I think your `new Model()` overrides the provided `ModelId`, causing EF to insert a new model and assign its PK (being 1) to `ModelId`. Try assigning `null` to `Vehicle.Model` instead, or set its state to unchanged, or create a `new Model { Id = 10 }`. – CodeCaster Apr 17 '18 at 07:35
  • 1
    As a rule of thumb, *never* initialize the *reference* navigation properties. See https://stackoverflow.com/questions/20757594/ef-codefirst-should-i-initialize-navigation-properties, EF Core is not different in that regard. – Ivan Stoev Apr 17 '18 at 07:42
  • @CodeCaster is correct. By setting the navigation property, you're telling EF to create a new `Model`, and then since you've also associated it with your vehicle, EF must backfill `ModelId` with the new `Model`s id to maintain the relationship. – Chris Pratt Apr 17 '18 at 13:03

0 Answers0