0

This the table structure I have:

#region Tables
public class WorkoutProfile
{
    public WorkoutProfile()
    {
        WorkoutExercises = new List<WorkoutExercise>();
    }
    [Key]
    public int ProfileId { get; set; }
    public string Name { get; set; }
    public int Sets { get; set; }
    public int RestAfterSetInSeconds { get; set; }
    public virtual User User { get; set; }
    public virtual ICollection<WorkoutExercise> WorkoutExercises { get; set; }
}

public class WorkoutExercise
{
    [Key]
    public int WorkoutId { get; set; }
    public virtual Exercise Exercise { get; set; }
    public int Order { get; set; }
    public int WorkoutTimeInSeconds { get; set; }
    public int RestAfterInSeconds { get; set; }
}

public class Exercise
{
    [Key]
    public long ExerciseId { get; set; }
    public string Title { get; set; }
    public string Visualisation { get; set; }
    public bool IsDefault { get; set; } // Is exersice should be included when user first registers
}

public class User
{
    [Key]
    public long UserId { get; set; }
    public string Email { get; set; }
    public DateTime Registered { get; set; }
}
#endregion Tables

In the repository class I run the following linq query:

return context
            .WorkoutProfiles.Include(w => w.WorkoutExercises)
            .Where(q => q.User.UserId == userId && q.ProfileId == profileId)
            .FirstOrDefault();

and I receive the good and old "Object reference not set to an instance of an object". When examining the result, see that Exercises property in WorkoutExercises is null.

This is how the database is created using code first approach:

enter image description here

So, the question is: why Exercises not included in WorkoutExercises object? Do I need to include it somehow? I am using .NET Core 2

eddyuk
  • 4,110
  • 5
  • 37
  • 65
  • Hello, I do not see any foreign key on the workout exercises table on your entity model. Do you have more configuration on DbContext.OnCreating maybe ? Also i see you dont include the User table on your statement. Maybe after all the null reference is the User Object? – Nick Polyderopoulos Feb 25 '18 at 01:34
  • Hi, thanks for answer. The foreign key is being figured out by EF, no implicit indication needed as far as I know (I also see it in the database). User is actually being loaded without a problem without Include statement, I guess it is because a child of main object that is being queried. – eddyuk Feb 25 '18 at 05:28

2 Answers2

1

The simple answer would be no lazy loading in EFCore. Not Released yet but if you want to dabble with alpha code, its in the repository. Based on your classes there are no collections for exercises in WorkoutExcercise.

Then you need to ThenInclude(w => w.Exercises) following your Include clause since EFCore doesn't do lazy loading.

mvermef
  • 3,814
  • 1
  • 23
  • 36
  • Hi, thanks for answer. Exercise does not suppose to be a collection in WorkoutExercises but a navigation property. It more like extends Exercises table for workout purposes. Logically, you have a list of exercises which you can choose from in your workout routine. – eddyuk Feb 25 '18 at 05:33
  • Updated answer to include a possible solution to your query – mvermef Feb 25 '18 at 06:14
  • I actually tried that before posting, EF says that Exercises has no relations to WorkoutProfiles table – eddyuk Feb 25 '18 at 12:50
  • Which would be correct as I suspect I think there needs to be more to your class or to a mapping in the context – mvermef Feb 25 '18 at 15:18
  • Since you coded the property as you would for EF6 lazy loading it will not work in EFCORE – mvermef Feb 25 '18 at 15:19
0

I found a solution following this post

Altered my code as following:

var top = context
            .Set<WorkoutProfile>()
            .Where(q => q.ProfileId == profileId && q.User.UserId == userId)
            .Include(q => q.WorkoutExercises)
            .SingleOrDefault();

        context
            .Entry(top)
            .Collection(e => e.WorkoutExercises)
            .Query()
            .OfType<WorkoutExercise>()
            .Include(e => e.Exercise)
            .Load();

And it worked

eddyuk
  • 4,110
  • 5
  • 37
  • 65