EF7 doesn't support lazy loading of child objects, but does support the .Include()
function. That being said, I'm struggling with something and am not sure if it just isn't possible in EF7, or I've just been staring at this too long.
Suppose something like the following (checking reg.Activities.Task.Ordinal
(an int
), Task is always null, even when I check the DB myself and am certain there is in fact a related record)...
public void SomeOtherMethod()
var r = getRegistration(User.UserName);
var act = r.Activities
.Where(a => a.IsDone == false) // unfinished
.OrderByDescending(o => o.Task.Ordinal) // Task indicates activity type, is always null
.FirstOrDefault(); // to get a user's most recent unfinished activity
//DO SOMETHING WITH ACT
}
public Registration getRegistration(string userName) {
var reg = _context.Registrations
.Where(r => r.User.UserName == userName) // this works however?
.Include(r => r.Acvitities) // List<Activity>
.FirstOrDefault();
return reg;
}
...I have the navigation properties in place in the model classes, but .Task
above is null and not loaded.
Further, since the query has been projected, I can't .Include
additional properties any more in the creation of act
. I cant .ThenInclude
in the creation of reg
because class Registration
does not include a definition for a Task
property (but Registration
does have a collection of Activities
that are List<Activity>
, and Activity
does have a Task
that is related to another table/class that defines the tasks and the order they should be presented to users per Activity
.
I've tried various incantations of .Join
, .Include
and .ThenInclude
hoping to be able to join the Task
to each of the Activities
while returning the Registration
object, but this fails because Registration
itself does not contain a Task
property.
I considered creating a new issue on GitHub, but am not yet certain that it isn't very doable and I'm just not looking at this correctly.
UPDATE1: Mihail suggested using... .Include(r => r.Activities.Select(resp => resp.Responses))
...but this yields an exception. This SO (https://stackoverflow.com/a/30151601/3246805) indicates thats for EF5 and that .ThenInclude
should be used.
However, trying that suggestion... .ThenInclude(r => r.Select(t => t.Task))
...yields the following Exception...
The properties expression 'r => {from Activity t in r select [t].Task}' is not valid. The expression should represent a property access: 't => t.MyProperty'. When specifying multiple properties use an anonymous type: 't => new { t.MyProperty1, t.MyProperty2 }'.
Parameter name: propertyAccessExpression
UPDATE2: Stafford asked for schema. Best effort at a sharable repo...
public class RegistrationData {
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public MyUser User { get; set; } // MyUser : IdentityUser
//blah blah, more fields
public List<UserTask> Activitys { get; set; }
}
public class UserTask {
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public bool IsDone { get; set; } = false;
[Required]
public int RegistrationId { get; set; }
[Required]
public RegistrationData Registration { get; set; }
[Required]
public int TaskId { get; set; }
[Required]
public Task Task { get; set; }
public List<UserResponse> Responses { get; set; }
}
public class Task {
[Required]
[DatabaseGenerated(DatabaseGeneratedOption.None)] // ID comes from loaded config
public int Id { get; set; }
[StringLength(20, MinimumLength = 1)]
public string Name { get; set; }
[Required]
public int Ordinal { get; set; }
[Required]
public int GroupId { get; set; }
}
public class UserResponse {
[Required]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public int UserTaskId { get; set; }
[Required]
public int QuestionNumber { get; set; }
}
Use Include
followed by ThenInclude
for the child's child properties. The child properties may not show up in intellisense for ThenInclude
, but just enter it anyway - it will compile and operate as expected.
var reg = _context.Registrations
.Where(r => r.User.UserName == userName)
.Include(r => r.Acvitities).ThenInclude(a => a.Task)
.Include(r => r.Activities).ThenInclude(a => a.SomethingElse)
.FirstOrDefault();
return reg;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With