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;
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 (.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;