How do you model 1x0..1 relations (optional one-to-one) in the Entity Framework Code First?

1

When an Entity MAY have one (and only one) instance of another Entity, but the second Entity MUST have the first, how is Entity Modeling done?

    
asked by anonymous 31.01.2014 / 19:50

1 answer

2

Suppose two models: Drivers (drivers) and Vehicles (vehicles). Suppose a driver does not necessarily have a vehicle, so you can first create a driver and then assign a vehicle to him:

Templates:

public class Driver
{
    [Key]
    public Guid DriverId { get; set; }
    public Guid? VehicleId { get; set; }

    public virtual Vehicle Vehicle { get; set; }
}

public class Vehicle
{
    [Key]
    public Guid VehicleId { get; set; }
    public Guid DriverId { get; set; }

    public virtual Driver Driver { get; set; }
}

Drivers:

public class DriversController : Controller
{
    private TesteMarotoContext context = new TesteMarotoContext();

    //
    // GET: /Drivers/

    public ViewResult Index()
    {
        return View(context.Drivers.Include(driver => driver.Vehicle).ToList());
    }

    //
    // GET: /Drivers/Details/5

    public ViewResult Details(System.Guid id)
    {
        Driver driver = context.Drivers.Single(x => x.DriverId == id);
        return View(driver);
    }

    //
    // GET: /Drivers/Create

    public ActionResult Create()
    {
        ViewBag.PossibleVehicles = context.Vehicles;
        return View();
    } 

    //
    // POST: /Drivers/Create

    [HttpPost]
    public ActionResult Create(Driver driver)
    {
        if (ModelState.IsValid)
        {
            driver.DriverId = Guid.NewGuid();
            context.Drivers.Add(driver);
            context.SaveChanges();

            if (driver.VehicleId != null)
            {
                var vehicle = context.Vehicles.Single(v => v.VehicleId == driver.VehicleId);
                vehicle.DriverId = driver.DriverId;
                context.Entry(vehicle).State = EntityState.Modified;
                context.SaveChanges();
            }

            return RedirectToAction("Index");  
        }

        ViewBag.PossibleVehicles = context.Vehicles;
        return View(driver);
    }

    //
    // GET: /Drivers/Edit/5

    public ActionResult Edit(System.Guid id)
    {
        Driver driver = context.Drivers.Single(x => x.DriverId == id);
        ViewBag.PossibleVehicles = context.Vehicles;
        return View(driver);
    }

    //
    // POST: /Drivers/Edit/5

    [HttpPost]
    public ActionResult Edit(Driver driver)
    {
        if (ModelState.IsValid)
        {
            context.Entry(driver).State = EntityState.Modified;
            context.SaveChanges();

            if (driver.VehicleId != null)
            {
                var vehicle = context.Vehicles.Single(v => v.VehicleId == driver.VehicleId);
                vehicle.DriverId = driver.DriverId;
                context.Entry(vehicle).State = EntityState.Modified;
                context.SaveChanges();
            }

            return RedirectToAction("Index");
        }
        ViewBag.PossibleVehicles = context.Vehicles;
        return View(driver);
    }

    //
    // GET: /Drivers/Delete/5

    public ActionResult Delete(System.Guid id)
    {
        Driver driver = context.Drivers.Single(x => x.DriverId == id);
        return View(driver);
    }

    //
    // POST: /Drivers/Delete/5

    [HttpPost, ActionName("Delete")]
    public ActionResult DeleteConfirmed(System.Guid id)
    {
        Driver driver = context.Drivers.Single(x => x.DriverId == id);
        context.Drivers.Remove(driver);
        context.SaveChanges();
        return RedirectToAction("Index");
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing) {
            context.Dispose();
        }
        base.Dispose(disposing);
    }
}

Note that you need to hit the Id's manually (by contrast).

    
31.01.2014 / 19:59