Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

EF 6 - One To Many Mapping Always Null

I can't seem to resolve my mapping issue; The relationship is one user may have many venues, A venue must have a user.

My venue class looks like:

public class Venue : BaseObject, IBaseObject
{
    [Required]
    public virtual User Owner { get; set; }

    [Required]
    [MaxLength(50)]
    public string Name { get; set; }
}

My User class looks like:

public class User : BaseObject, IBaseObject
{

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

    [Required]
    [DisplayName("Email")]
    public string EmailAddress { get; set; }

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

    public bool Active { get; set; }


    public virtual ICollection<Venue> Venues { get; set; } 
}

DbContextClass as requested

 public class SystemContext : DbContext, IDbContext
{
    public SystemContext() :
        base("SystemContext")
    {
        Database.SetInitializer<SystemContext>(null);
        Configuration.ProxyCreationEnabled = false;
        Configuration.LazyLoadingEnabled = true;
    }


    public SystemContext(string connectionstringname = "SystemContext") :
        base(connectionstringname)
    {
        Database.SetInitializer<SystemContext>(null);
        Configuration.ProxyCreationEnabled = false;


    }
    public new IDbSet<T> Set<T>() where T : class
    {
        return base.Set<T>();
    }


    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.Entity<User>().HasMany(x=>x.Venues);
    }



    public DbSet<PublicQueries> PublicQueries { get; set; }
    public DbSet<Venue> Venues { get; set; }
    public DbSet<User> Users { get; set; }
}

When I load the User class from the database Venues always seems to be null?

I've done something similar before but can't remember how I resoled this.

Thanks

like image 810
Lemex Avatar asked Feb 23 '14 15:02

Lemex


2 Answers

Pretty sure this is a lazy-load issue. If you load an object with navigation properties such as your ICollection<Venues> then they won't be included by default, because they might have more navigation properties linking to more objects, which may have more navigation properties... and before you know it you're loading half the database. This is a particular problem when you've disposed of the context the object came out of by the time you go to access that navigation property, because then it doesn't have a database connection to load them from even if it did realise that it should be doing so.

The fix is to tell Entity Framework that you want that property to be populated, by adding .Include(u => u.Venues); when you get them from the DbSet. You'll need to include System.Data.Entity to get that particular overload of Include().

like image 58
anaximander Avatar answered Nov 04 '22 03:11

anaximander


You venue class should also have a field called OwnerId.

You can take this link as reference as a start for lazy loading.

public class Venue : BaseObject, IBaseObject
{
    public (int/guid/or other type if you want) OwnerId{get;set;}

    [Required]
    public virtual User Owner { get; set; }

    [Required]
    [MaxLength(50)]
    public string Name { get; set; }
}

then also make sure your User class has some Id field which will then be used as foreign Key by EF

This is what I would do,

public class Venue : BaseObject, IBaseObject
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id{get;set;}

    public int OwnerId{get;set;}

    [Required]
    public virtual User Owner { get; set; }

    [Required]
    [MaxLength(50)]
    public string Name { get; set; }
}

public class User : BaseObject, IBaseObject
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id {get;set;}

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

    [Required]
    [DisplayName("Email")]
    public string EmailAddress { get; set; }

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

    public bool Active { get; set; }


    public virtual ICollection<Venue> Venues { get; set; } 
}
like image 3
Cybercop Avatar answered Nov 04 '22 05:11

Cybercop