Ef7 cannot restore properties of child objects of child collections

EF7 does not support lazy loading of child objects , but supports the .Include() function. That being said, I'm struggling with something and not sure if this is simply not possible in EF7, or I just looked at it for too long.

Suppose something like the following (check reg.Activities.Task.Ordinal (a int ), the task is always null, even when I check the database itself and am sure that there is actually 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 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 navigation properties in model classes, but .Task above is null and does not load.

Also, since the request was projected, I can no longer .Include additional properties in the creation of act . I cannot .ThenInclude in creating reg because the Registration class does not include a definition for the Task property (but Registration has a set of Activities that List<Activity> , and Activity > has a Task that is associated with another table / class that defines tasks and the order in which they are presented to users in Activity .

I tried various spells .Join , .Include and .ThenInclude , hoping that I could join the Task to each of the Activities , returning the Registration object, but this fails because Registration by itself does not contain the Task property.

I thought about creating a new problem on GitHub, but still not sure if this is not very doable, and I just don't look at it right.


UPDATE1: Michael suggested using ...
.Include(r => r.Activities.Select(resp => resp.Responses))
... but this gives an exception. This SO ( https://stackoverflow.com/a/3184168/ ) indicates that for EF5 and that .ThenInclude should be used.

However, having tried this suggestion ...
.ThenInclude(r => r.Select(t => t.Task))
... gives 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 a circuit. The best effort in a joint 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; } } 
+5
source share
1 answer

Use Include , and then ThenInclude for child children properties. Child properties may not appear in intellisense for ThenInclude , but just enter it anyway - it will compile and work 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; 
+12
source

Source: https://habr.com/ru/post/1238481/


All Articles