Entity framework navigation property is null

13,214

Because you are disposing of your BackofficeContext you cannot use LazyLoading, which is what is happening when you make Settings virtual.

You can either increase the lifetime of your BackofficeContext, or eager load Settings. You can use eager loading with Include.

public SettingCategory Get(Guid settingCategoryId)
{
    using (var context = new BackofficeContext())
    {
        return context
            .SettingCategories
            .Include(s => s.Settings)
            .FirstOrDefault(s => s.SettingCategoryId == settingCategoryId);
    }
}
Share:
13,214
Roger Far
Author by

Roger Far

.NET programmer!

Updated on June 04, 2022

Comments

  • Roger Far
    Roger Far almost 2 years

    I have 2 simple classes:

    public class Setting
    {
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public Guid SettingId { get; set; }
    
        [Required]
        public String Name { get; set; }
    
        public String Value { get; set; }
    
        [Required]
        public SettingCategory SettingCategory { get; set; }
    }
    
    public class SettingCategory
    {
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public Guid SettingCategoryId { get; set; }
    
        [Required]
        public String Value { get; set; }
    
        public ICollection<Setting> Settings { get; set; }
    }
    

    When I retrieve a SettingCategory from the database the collection Settings is always null.

    When I make it a virtual then it will say: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

    How can I access my Settings list?

    The other way around works, if I retrieve a Setting from the database the SettingCategory property is filled.

    This is my initial code-migrations script:

    CreateTable(
        "dbo.Settings",
        c => new
            {
                SettingId = c.Guid(nullable: false, identity: true),
                Name = c.String(nullable: false),
                Value = c.String(),
                SettingCategory_SettingCategoryId = c.Guid(nullable: false),
            })
        .PrimaryKey(t => t.SettingId)
        .ForeignKey("dbo.SettingCategories", t => t.SettingCategory_SettingCategoryId, cascadeDelete: true)
        .Index(t => t.SettingCategory_SettingCategoryId);
    
    CreateTable(
        "dbo.SettingCategories",
        c => new
            {
                SettingCategoryId = c.Guid(nullable: false, identity: true),
                Value = c.String(nullable: false),
            })
        .PrimaryKey(t => t.SettingCategoryId);
    

    And this is the part that gets it from the database:

    public SettingCategory Get(Guid settingCategoryId)
    {
        using (var context = new BackofficeContext())
        {
            return context
                .SettingCategories
                .FirstOrDefault(s => s.SettingCategoryId == settingCategoryId);
        }
    }
    

    Answer

    I forgot the include in .SettingCategories, but I was trying it with a lambda:

    public SettingCategory Get(Guid settingCategoryId)
    {
        using (var context = new BackofficeContext())
        {
            return context
                .SettingCategories
                .Include(s => s.Settings)
                .FirstOrDefault(s => s.SettingCategoryId == settingCategoryId);
        }
    }
    

    That doesn't work, but this does:

    public SettingCategory Get(Guid settingCategoryId)
    {
        using (var context = new BackofficeContext())
        {
            return context
                .SettingCategories
                .Include("Settings")
                .FirstOrDefault(s => s.SettingCategoryId == settingCategoryId);
        }
    }