Mubsher Mughal
Mubsher Mughal

Reputation: 442

EF MVC4 returning null after updating entries in many to many relationship

I have a many to many relationship b/w drivers and vehicle entity, at the time of driver creation, many vehicles can be assigned to a driver, it works fine, but when I want to edit and update records I am getting null collection of vehicles,

Here are my Models :

 public class Driver {
   public int driverId {get;set;}
   public string Name {get;set;}
   public virtual ICollection<Vehicle> Vehicles {get;set;}
 } 
 public class Vehicle {
   public int Vehicle_Id {get;set;}
   public string Vehicle_Type_Name {get;set;}
   public virtual ICollection<Driver> Drivers {get;set;}
 } 

Here I define the relationship:

   modelBuilder
    .Entity<Driver>()
    .HasMany<Vehicle>(d => d.Vehicles)
    .WithMany(d => d.Drivers).Map(
  cs =>
   {                   
      cs.MapLeftKey("DriverId")
      .MapRightKey("VehicleId")
      .ToTable("DriversVehicles");
   });

And my driver View Model

public class DriverViewModel
{
    public DriverViewModel()
    {
        SelectedVehicles=new List<int>();
        VehicleList = new List<Vehicle>();
    }

    public Driver driver { get; set; }
    public List<int> SelectedVehicles { get; set; }
    public List<Vehicle> VehicleList { get; set; }
}

And here is driver Edit() Controller Action :

    public ActionResult Edit(int id = 0)
    {
        DriverViewModel DriverVm = new DriverViewModel();


        var list = db.vehicles.Select(
        v => new { v.Vehicle_Id,v.Vehicle_Type_Name }).ToList();
        DriverVm.driver = db.drivers.Find(id);

        foreach (var item in list)
        {
            DriverVm.VehicleList.Add(new Vehicle { Vehicle_Id = item.Vehicle_Id, Vehicle_Type_Name = item.Vehicle_Type_Name });
        }
        foreach (var item in DriverVm.driver.Vehicles)
        {
            DriverVm.SelectedVehicles.Add(item.Vehicle_Id);
        }

        return View(DriverVm);
    }

And here is POST action for edit:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit(DriverViewModel driverVm)
    {
        var list = db.vehicles.Select(v =>
            new { v.Vehicle_Id, v.Vehicle_Type_Name }).ToList();

        foreach (var item in list)
        {
            driverVm.VehicleList.Add(
         new Vehicle { 
             Vehicle_Id = item.Vehicle_Id, 
             Vehicle_Type_Name = item.Vehicle_Type_Name 
        });
        }

        if (ModelState.IsValid)
        {
            db.Entry(driverVm.driver).State = EntityState.Modified;
            db.SaveChanges();

            List<Vehicle> vhcls = new List<Vehicle>();

            Driver driver = db.drivers.Find(driverVm.driver.driverId);
            vhcls = driver.Vehicles.ToList();

            foreach (Vehicle veh in vhcls)
            {
                driver.Vehicles.Remove(veh);
            }
            db.SaveChanges();

            foreach (var item in driverVm.SelectedVehicles)
            {
               Vehicle vehicle = db.vehicles.Find(item);
               driverVm.driver.Vehicles.Add(vehicle);
            }
            db.SaveChanges();

            TempData["DriverSuccess"] = "1";
            return RedirectToAction("Edit");
        }
        else
        {
            ViewBag.DriverError = "1";
        }
        return View(driverVm);
    }

The actual problem is here :

        Driver driver = db.drivers.Find(driverVm.driver.driverId);
        vhcls = driver.Vehicles.ToList();

        foreach (Vehicle veh in vhcls)
        {
            driver.Vehicles.Remove(veh);
        }
        db.SaveChanges()

The list "vhcls" in the above code is empty, it should contain the vehicles associated with drivers, but "driver" object contains Null collection in "driverVm.driver.Vehicles" instead of having associated vehicles, I am wandering badly but can't find the solution..Please help......

Upvotes: 0

Views: 31

Answers (1)

Devin Goble
Devin Goble

Reputation: 2857

Just using find won't include related entities. It's very likely that driver contains the right entity, but that the Vehicles collection is empty.

Try using Include to make sure that the related entities will be included, and FirstOrDefault to emulate the result of Find.

Driver driver = db.drivers
    .Include(d => d.Vehicles)
    .FirstOrDefault(d => d.Id == driverVm.driver.driverId);

vhcls = driver.Vehicles.ToList();

Edit: I initially missed that you were already using Lazy Loading, so I adjusted the answer a bit.

Upvotes: 1

Related Questions