ef7 无法检索子集合的子对象的属性

ef7 unable to retrieve child collections' child object's properties

EF7 doesn't support lazy loading of child objects,但支持.Include()功能。话虽这么说,我正在努力解决一些问题,但不确定它是否在 EF7 中是不可能的,或者我一直盯着它看太久了。

假设如下(检查reg.Activities.Task.Ordinal(一个int),任务始终为空,即使我自己检查数据库并确定实际上有相关记录)。 ..

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;
}

...我在模型 classes 中放置了 navigation properties,但上面的 .Task 为空且未加载。

此外,由于查询已被投影,我无法在 act 的创建中再 .Include 其他属性。我不能 .ThenInclude 创建 reg 因为 class Registration 不包含 Task 属性 的定义(但是 Registration 确实有一个 Activities 的集合 List<Activity>,并且 Activity 确实有一个 Task 与另一个 table/class 相关,后者定义了任务和顺序它们应该按照 Activity.

呈现给用户

我尝试了 .Join.Include.ThenInclude 的各种咒语,希望能够将 Task 加入每个 Activities在返回 Registration 对象时,但这失败了,因为 Registration 本身不包含 Task 属性.

我考虑过在 GitHub 上创建一个新问题,但我不确定它是否可行,我只是没有正确看待它。


更新 1: Mihail 建议使用...
.Include(r => r.Activities.Select(resp => resp.Responses))
...但这会产生异常。此 SO () 表明那是 EF5 并且应该使用 .ThenInclude

但是,尝试那个建议...
.ThenInclude(r => r.Select(t => t.Task))
...产生以下异常...

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:斯塔福德要求架构。尽最大努力创建一个可共享的存储库...

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; }
}

使用 Include,然后使用 ThenInclude 作为 child 的 child 属性。 child 属性可能不会显示在 ThenInclude 的智能感知中,但无论如何只需输入它 - 它会按预期编译和运行。

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;