Search code examples
c#entity-frameworklinqeager-loading

EF6 Optional 1:1 include not working


Trying to set up basic EF6 Optional 1:1. Extremely frustrating. I have read lots and lost of posts.

I have two entities, Guests and Seats, each one can exist on their own, a seat does not need a guest and a guest does not need a seat.

Guest Model:

        public int ID { get; set; }

        public int? SeatID { get; set; }

        [Required]
        public string FirstName { get; set; }

        //Link to Seat
        public Seat Seat { get; set; }

Seat Model:

        public int ID { get; set; }

        public int? GuestID { get; set; }

        [Required]
        public string SeatNumber { get; set; }

        public bool Occupied { get { return (GuestID == null ? true : false); } }

        //Link to Guest
        public Guest Guest{ get; set; }

I had lots of problems just getting to this point. I had to add this to my model creation for the relationship to work:

       modelBuilder.Entity<Seat>()
            .HasOptional(g => g.Guest)
            .WithOptionalDependent(s => s.Seat);

Now my application is working however when I try and load related data with the include method it just comes up blank, nothing there.

var seats = db.Seats.Include(s => s.Guest);
            return View(seats.ToList());

On my view I use

@Html.DisplayFor(modelItem => item.Guest.FirstName)

I want to know how to make the include statement work, preferably without lazy loading (or even with if i have to). Also, I do not want to have a SeatAssignment table, I considered going down this road.

I could use a Viewmodel for this to work but i dont understand why the 1:1 optional is not loading the related data.

As requested, here is the generated schema...definitely something odd going on here. As a side note i can make it work with a viewmodel, but i dont want to.

Schema


Solution

  • You have to construct your models as shown below.

    public class Guest
    {
            public int GuestId { get; set; }
    
            [Required]
            public string FirstName { get; set; }
    
            //Link to Seat
            public virtual Seat Seat { get; set; }
    }
    
    public class Seat
    {
            public int SeatId { get; set; }
    
            [Required]
            public string SeatNumber { get; set; }
    
            public bool Occupied { get { return (GuestID == null ? true : false); }}
    
            //Link to Guest
            public virtual Guest Guest{ get; set; }
    }
    

    Fluent API mapping :

      modelBuilder.Entity<Seat>()
                .HasOptional(g => g.Guest)
                .WithOptionalDependent(s => s.Seat);
    

    Then :

    var seats = db.Seats.Include(s => s.Guest).ToList();